@@ -123,6 +123,9 @@ FastCopy::FastCopy()
123
123
mainThread_pt = QThread::currentThreadId ();
124
124
// 実行フェーズを「実行前」に変更
125
125
phase = NORUNNING;
126
+
127
+ ltfs_prohibitlist << LTFS_PROHIBIT_SLASH;
128
+ ltfs_prohibitlist << LTFS_PROHIBIT_COLON;
126
129
}
127
130
128
131
FastCopy::~FastCopy ()
@@ -1665,6 +1668,9 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
1665
1668
BOOL confirm_dir_local = confirm_dir || is_rename_local;
1666
1669
1667
1670
isRename = FALSE ; // top level のみ効果を出す
1671
+ // v125 LTFS,ODAの禁則文字置き換えワーク
1672
+ char wk_filename[MAX_PATH];
1673
+ unsigned long wk_hashVal;
1668
1674
1669
1675
if (waitTick) Wait (1 );
1670
1676
@@ -1688,7 +1694,24 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
1688
1694
for (srcStat = (FileStat *)fileStatBuf.Buf (); srcStat < statEnd;
1689
1695
srcStat = (FileStat *)((BYTE *)srcStat + srcStat->size )) {
1690
1696
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
+ }
1692
1715
}
1693
1716
int path_len = 0 ;
1694
1717
srcStat->fileID = nextFileID++;
@@ -1711,7 +1734,12 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
1711
1734
|| (info.flags & FILE_REPARSE))) {
1712
1735
/* 比較モード */
1713
1736
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
+ }
1715
1743
strcpyV (MakeAddr (src, dir_len), srcStat->cFileName );
1716
1744
CheckSuspend ();
1717
1745
if (!IsSameContents (srcStat, dstStat) && !isAbort) {
@@ -1762,6 +1790,25 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
1762
1790
for (srcStat = (FileStat *)(dirStatBuf.Buf () + curDirStatSize); srcStat < statEnd;
1763
1791
srcStat = (FileStat *)((BYTE *)srcStat + srcStat->size )){
1764
1792
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
+
1765
1812
if ((dstStat = hash.Search (srcStat->upperName , srcStat->hashVal )) != NULL ){
1766
1813
// srcStat->isCaseChanged = strcmpV(srcStat->cFileName, dstStat->cFileName);
1767
1814
if (is_rename_local){
@@ -1841,8 +1888,17 @@ BOOL FastCopy::ReadProc(int dir_len, BOOL confirm_dir)
1841
1888
new_dir_len = dir_len + sprintfV (MakeAddr (src, dir_len), FMT_STR_V, srcStat->cFileName );
1842
1889
srcStat->fileID = nextFileID++;
1843
1890
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
+ }
1846
1902
1847
1903
if (!isListingOnly) {
1848
1904
// ディレクトリへのシンボリックリンクskip確定してないか最初にチェック
@@ -2490,6 +2546,11 @@ BOOL FastCopy::ReadDirEntry(int dir_len, BOOL confirm_dir)
2490
2546
caseHash.clear ();
2491
2547
}
2492
2548
2549
+ if (info.flags_second & LTFS_MODE){
2550
+ // 禁則文字自動置換後のファイル名/フォルダ名格納ハッシュ
2551
+ archiveHash.clear ();
2552
+ }
2553
+
2493
2554
// リンクは実体としてコピー?
2494
2555
if (info.flags & DIR_REPARSE || info.flags & FILE_REPARSE){
2495
2556
wk_rtn = stat ((const char *)src,&fdat);
@@ -2688,6 +2749,18 @@ BOOL FastCopy::ReadDirEntry(int dir_len, BOOL confirm_dir)
2688
2749
continue ;
2689
2750
}
2690
2751
// ディレクトリ&ファイル情報の蓄積
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
+ }
2691
2764
if (IsDir (fdat.st_mode )) {
2692
2765
// ディレクトリやな
2693
2766
len = FdatToFileStat (&fdat, (FileStat *)(dirStatBuf.Buf () + dirStatBuf.UsedSize ()),
@@ -3622,7 +3695,7 @@ BOOL FastCopy::ReadDstStat(void)
3622
3695
goto END;
3623
3696
}
3624
3697
dstStatIdx[num++] = dstStat;
3625
- len = FdatToFileStat (&fdat, (FileStat *)dstStat,TRUE ,wk_filename);
3698
+ len = FdatToFileStat (&fdat, (FileStat *)dstStat,TRUE ,wk_filename, false );
3626
3699
dstStatBuf.AddUsedSize (len);
3627
3700
dstStatIdxBuf.AddUsedSize (sizeof (FileStat *));
3628
3701
if (dstStatBuf.RemainSize () <= maxStatSize && !dstStatBuf.Grow (MIN_ATTR_BUF)) {
@@ -3641,7 +3714,7 @@ BOOL FastCopy::ReadDstStat(void)
3641
3714
/* FindFirstFileはdir単体を指定すると中のファイルエントリを調査せずにdirエントリだけ返す謎仕様 */
3642
3715
/* FindFirstFileの挙動エミュレートのために、dir情報だけ登録してリターンしちゃうぞ */
3643
3716
dstStatIdx[num++] = dstStat;
3644
- len = FdatToFileStat (&fdat, (FileStat *)dstStat,TRUE ,wk_filename);
3717
+ len = FdatToFileStat (&fdat, (FileStat *)dstStat,TRUE ,wk_filename, false );
3645
3718
dstStatBuf.AddUsedSize (len);
3646
3719
dstStatIdxBuf.AddUsedSize (sizeof (FileStat *));
3647
3720
@@ -3717,7 +3790,7 @@ BOOL FastCopy::ReadDstStat(void)
3717
3790
// 事前調査対象として適切なファイルかどうか判定。
3718
3791
if (IsFile (fdat.st_mode ) || IsDir (fdat.st_mode ) || IsSlnk (fdat.st_mode )){
3719
3792
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 );
3721
3794
dstStatBuf.AddUsedSize (len);
3722
3795
3723
3796
// 次の stat 用 buffer のセット
@@ -4396,6 +4469,13 @@ BOOL FastCopy::WriteProc(int dir_len)
4396
4469
total.linkFiles ++;
4397
4470
}
4398
4471
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
+ }
4399
4479
// verifyモード時は、dstに存在しないファイルがあったらエラーとする
4400
4480
if (info.mode == VERIFY_MODE){
4401
4481
// エラー要因を確認
@@ -4563,6 +4643,13 @@ BOOL FastCopy::WriteDirProc(int dir_len)
4563
4643
if (mkdirQueueBuf.UsedSize ()){
4564
4644
ExecDirQueue ();
4565
4645
}
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
+ }
4566
4653
if (isListingOnly || !mkdir ((const char *)dst, 0777 )){
4567
4654
if (isListing && !is_reparse){
4568
4655
if (info.mode == VERIFY_MODE){
@@ -5431,6 +5518,14 @@ BOOL FastCopy::WriteFileProc(int dst_len,int parent_fh)
5431
5518
else {
5432
5519
// xattr延長の再帰でWriteFileProcが呼ばれてない?(最初のファイル実体writeか?)
5433
5520
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
+ }
5434
5529
// 書き込み対象のファイルハンドルをopen
5435
5530
5436
5531
// LTFSへの書き込みで禁則文字の":"や"/"を発見した場合は
@@ -5607,10 +5702,12 @@ BOOL FastCopy::WriteFileProc(int dst_len,int parent_fh)
5607
5702
memcpy (obj->path , dst, path_size);
5608
5703
5609
5704
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)){
5611
5707
phase = VERIFYING;
5612
5708
CheckDigests (is_empty_buf ? CD_WAIT : CD_NOWAIT); // empty なら wait
5613
5709
phase = COPYING;
5710
+ }
5614
5711
}
5615
5712
5616
5713
if (command == WRITE_BACKUP_FILE) {
@@ -5826,6 +5923,65 @@ BOOL FastCopy::WriteFileBackupAclLocal(int fh,ReqHeader *writereq)
5826
5923
return (ret);
5827
5924
}
5828
5925
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
+
5829
5985
BOOL FastCopy::ChangeToWriteModeCore (BOOL is_finish)
5830
5986
{
5831
5987
BOOL isResetRunMode = runMode == RUN_DIGESTREQ;
@@ -6301,7 +6457,7 @@ void FastCopy::signal_handler(int signum){
6301
6457
abort ();
6302
6458
}
6303
6459
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 )
6305
6461
{
6306
6462
6307
6463
stat->fileID = 0 ;
@@ -6335,7 +6491,7 @@ int FastCopy::FdatToFileStat(struct stat *fdat, FileStat *stat, BOOL is_usehash,
6335
6491
stat->hFile = SYSCALL_ERR; // file descripter
6336
6492
stat->lastError = 0 ;
6337
6493
stat->isExists = FALSE ;
6338
- stat->isCaseChanged = FALSE ;
6494
+ stat->isArchived = FALSE ;
6339
6495
stat->renameCount = 0 ;
6340
6496
stat->acl = NULL ;
6341
6497
stat->aclSize = 0 ;
@@ -6367,6 +6523,14 @@ int FastCopy::FdatToFileStat(struct stat *fdat, FileStat *stat, BOOL is_usehash,
6367
6523
// 4バイトを超えてぶっこんだ分も込みでサイズ長を設定
6368
6524
// FilestatのcFileNameまでのサイズ + CFileNameから始まる、ぶっこんだ分のサイズ
6369
6525
// が入ってるよ。ちなみに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
+
6370
6534
stat->size = len + offsetof (FileStat, cFileName);
6371
6535
stat->minSize = ALIGN_SIZE (stat->size , 8 );
6372
6536
0 commit comments