diff options
-rw-r--r-- | BUILD/Changelog.txt | 6 | ||||
-rw-r--r-- | BUILD/FreeFileSync.chm | bin | 672005 -> 670693 bytes | |||
-rw-r--r-- | BUILD/Help/html/Features.html | 99 | ||||
-rw-r--r-- | BUILD/Languages/chinese_simple.lng | 22 | ||||
-rw-r--r-- | BUILD/Resources.zip | bin | 272977 -> 272855 bytes | |||
-rw-r--r-- | file_hierarchy.cpp | 12 | ||||
-rw-r--r-- | file_hierarchy.h | 4 | ||||
-rw-r--r-- | lib/custom_grid.cpp | 6 | ||||
-rw-r--r-- | lib/parse_plural.h | 2 | ||||
-rw-r--r-- | ui/main_dlg.cpp | 10 | ||||
-rw-r--r-- | version/version.h | 2 | ||||
-rw-r--r-- | version/version.rc | 4 | ||||
-rw-r--r-- | zen/file_handling.cpp | 100 | ||||
-rw-r--r-- | zen/file_traverser.cpp | 2 |
14 files changed, 124 insertions, 145 deletions
diff --git a/BUILD/Changelog.txt b/BUILD/Changelog.txt index 7116b447..5e5d9053 100644 --- a/BUILD/Changelog.txt +++ b/BUILD/Changelog.txt @@ -2,6 +2,11 @@ |FreeFileSync| -------------- +Changelog v4.4 +-------------- +Fixed error copying files containing alternate data streams (Windows) + + Changelog v4.3 -------------- Detection of moved and renamed files @@ -11,6 +16,7 @@ Fixed synchronization result dialog GUI glitch (Windows XP) Fixed macro %weekday% RealtimeSync: Fixed support for manual volume unmount (Windows) Added Croatian language +Updated translation files Changelog v4.2 diff --git a/BUILD/FreeFileSync.chm b/BUILD/FreeFileSync.chm Binary files differindex cc0d3174..04ae52a9 100644 --- a/BUILD/FreeFileSync.chm +++ b/BUILD/FreeFileSync.chm diff --git a/BUILD/Help/html/Features.html b/BUILD/Help/html/Features.html index 784598ba..4b404317 100644 --- a/BUILD/Help/html/Features.html +++ b/BUILD/Help/html/Features.html @@ -5,7 +5,7 @@ <TITLE></TITLE> <META NAME="GENERATOR" CONTENT="OpenOffice.org 3.2 (Win32)"> <META NAME="CREATED" CONTENT="20091206;16574000"> - <META NAME="CHANGED" CONTENT="20110915;12485300"> + <META NAME="CHANGED" CONTENT="20111121;19582100"> <STYLE TYPE="text/css"> <!-- @page { margin: 2cm } @@ -20,68 +20,43 @@ </HEAD> <BODY LANG="de-DE" DIR="LTR"> <H3 CLASS="western"><FONT FACE="Tahoma, sans-serif">Key Features</FONT></H3> -<P STYLE="margin-bottom: 0cm"><BR> -</P> <OL> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Detection + of moved and renamed files</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Copy + locked files using Windows Volume Shadow Copy Service. (Windows + only)</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Support + for multiple folder pairs with distinct configuration</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Compare files (bytewise or by date) and synchronize them.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">No - limitations: An arbitrary number of files can be synchronized.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Unicode - support.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Network - support.</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Create + Batch Jobs for automated synchronization with or without GUI.</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Optimized + performance, coded in C++ completely.</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Native + 32 and 64 bit builds</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Transactional file copy</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Synchronization + database for propagation of deleted files and conflict detection</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Cross-Platform</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Full + support for Windows/Linux Symbolic Links and Windows Junction + Points.</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Full + unicode support.</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Full + network support.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Built-in support for very long filenames (more than MAX_PATH = 260 characters).</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Synchronization - database for propagation of deleted files and conflict detection</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Copy NTFS alternate data streams, compressed and encrypted file attributes</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Support - for multiple folder pairs with distinct configuration</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Full - support for Windows/Linux Symbolic Links and Windows Junction - Points.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Lean - & easily accessible UI: Highly optimized for speed and huge sets - of data.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Algorithms - coded in C++ completely.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">All - progress indicators optimized for maximum performance!</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Create - Batch Jobs for automated synchronization with or without GUI.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Focus - on usability:</FONT></P> - <OL TYPE=a> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Only - necessary functionality on UI: no overloaded menus or icon jungle.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Select - all folders via drag & drop.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Last - used configuration and screen settings are saved automatically.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Maintain - and load different configurations by drag & drop, load-button - or commandline.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Double-click - to start external application (e.g. show file in Windows Explorer)</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Copy - & paste all grid data as text</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Delete - superfluous/temporary files directly on main grid.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Right-click - context menu.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Comprehensive - status information and error reporting</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Sort - file-lists by name, size or date.</FONT></P> - </OL> -</OL> -<OL START=14> + & easily accessible UI: only useful functionality, no feature + bloat.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Support for filesizes larger than 4 GB.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Option @@ -89,28 +64,20 @@ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Ignore directories "\RECYCLER" and "\System Volume Information" with default filter. (Windows only)</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Localized - versions are available for many languages.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Delete before copy: Avoid disc space shortages for large sync-jobs.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Filter - functionality to include/exclude files from synchronization (without - requiring a re-compare!).</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Include/exclude - specific files from synchronization temporarily.</FONT></P> + functionality to include/exclude files from synchronization.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Automatically handle daylight saving time changes on FAT/FAT32 volumes.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Portable version available (selectable via installer).</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Native - 64-Bit version.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Check - for updates from within FreeFileSync automatically.</FONT></P> - <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Copy - locked files using Windows Volume Shadow Copy Service. (Windows - only)</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Opt-in + for automatic online update.</FONT></P> + <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Localized + versions are available for many languages.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Create - regular backups with macros %time%, %date% within directory names</FONT></P> + recurring backups with macros %time%, %date% within directory names</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Copy file create/modification times when synchronizing.</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Advanced @@ -119,5 +86,7 @@ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Case-sensitive synchronization of file, directory and symlink names</FONT></P> </OL> +<P STYLE="margin-bottom: 0cm"><BR> +</P> </BODY> </HTML>
\ No newline at end of file diff --git a/BUILD/Languages/chinese_simple.lng b/BUILD/Languages/chinese_simple.lng index 65887d4f..e71fbcee 100644 --- a/BUILD/Languages/chinese_simple.lng +++ b/BUILD/Languages/chinese_simple.lng @@ -499,10 +499,10 @@ The command line is executed each time: <target>操作:</target> <source>Items found:</source> -<target>已找到的元素:</target> +<target>已找到的项目:</target> <source>Items remaining:</source> -<target>剩余的元素:</target> +<target>剩余的项目:</target> <source>Speed:</source> <target>速度:</target> @@ -568,7 +568,7 @@ The command line is executed each time: <target><自动></target> <source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> -<target></target> +<target>使用一个数据库来识别和传播两边的改变. 删除,重命名和冲突会自动检测.</target> <source>Mirror ->></source> <target>镜像 ->></target> @@ -661,7 +661,7 @@ is the same <target>同步中...</target> <source>Items processed:</source> -<target>已处理的元素:</target> +<target>已处理的项目:</target> <source>&Pause</source> <target>暂停(&P)</target> @@ -790,7 +790,7 @@ Exclude: \stuff\temp\* <target>事务文件复制</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>首先写入到一个临时文件(*.ffs_tmp)然后再重命名. 这样即使出现致命错误也能保持一致的状态.</target> <source>Copy locked files</source> <target>复制被锁定的文件</target> @@ -877,16 +877,16 @@ Exclude: \stuff\temp\* <target>自动调整栏宽</target> <source>Icon size:</source> -<target></target> +<target>图标大小:</target> <source>Small</source> -<target></target> +<target>小</target> <source>Medium</source> -<target></target> +<target>中</target> <source>Large</source> -<target></target> +<target>大</target> <source>Include all rows</source> <target>包括所有行</target> @@ -1342,10 +1342,10 @@ Exclude: \stuff\temp\* <target>删除右侧文件/文件夹</target> <source>Move file on left</source> -<target></target> +<target>移动左侧的文件</target> <source>Move file on right</source> -<target></target> +<target>移动右侧的文件</target> <source>Overwrite left file/folder with right one</source> <target>从右侧覆盖左侧的文件/文件夹</target> diff --git a/BUILD/Resources.zip b/BUILD/Resources.zip Binary files differindex 9ad96f71..c4749b68 100644 --- a/BUILD/Resources.zip +++ b/BUILD/Resources.zip diff --git a/file_hierarchy.cpp b/file_hierarchy.cpp index 39b789fd..f5d2d28c 100644 --- a/file_hierarchy.cpp +++ b/file_hierarchy.cpp @@ -117,15 +117,15 @@ bool hasDirectChild(const HierarchyObject& hierObj, Predicate p) } -SyncOperation FileSystemObject::testSyncOperation(SyncDirection testSyncDir) const +SyncOperation FileSystemObject::testSyncOperation(SyncDirection testSyncDir, bool enabled) const { - return proposedSyncOperation(getCategory(), selectedForSynchronization, testSyncDir, syncDirConflict); + return proposedSyncOperation(getCategory(), enabled, testSyncDir, syncDirConflict); } SyncOperation FileSystemObject::getSyncOperation() const { - return FileSystemObject::testSyncOperation(syncDir); + return FileSystemObject::testSyncOperation(syncDir, selectedForSynchronization); //no *not* make a virtual call to testSyncOperation()! See FileMapping::testSyncOperation()! } @@ -205,9 +205,9 @@ SyncOperation DirMapping::getSyncOperation() const } -SyncOperation FileMapping::testSyncOperation(SyncDirection testSyncDir) const +SyncOperation FileMapping::testSyncOperation(SyncDirection testSyncDir, bool enabled) const { - SyncOperation op = FileSystemObject::testSyncOperation(testSyncDir); + SyncOperation op = FileSystemObject::testSyncOperation(testSyncDir, enabled); /* check whether we can optimize "create + delete" via "move": @@ -236,7 +236,7 @@ SyncOperation FileMapping::testSyncOperation(SyncDirection testSyncDir) const SyncOperation FileMapping::getSyncOperation() const { - return FileMapping::testSyncOperation(getSyncDir()); + return FileMapping::testSyncOperation(getSyncDir(), isActive()); } diff --git a/file_hierarchy.h b/file_hierarchy.h index cfa71ab2..ac7ed87d 100644 --- a/file_hierarchy.h +++ b/file_hierarchy.h @@ -348,7 +348,7 @@ public: virtual CompareFilesResult getCategory() const = 0; virtual std::wstring getCatConflict() const = 0; //only filled if getCategory() == FILE_CONFLICT //sync operation - virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; + virtual SyncOperation testSyncOperation(SyncDirection testSyncDir, bool enabled) const; virtual SyncOperation getSyncOperation() const; std::wstring getSyncOpConflict() const; //return conflict when determining sync direction or during categorization @@ -491,7 +491,7 @@ public: virtual CompareFilesResult getCategory() const; virtual std::wstring getCatConflict() const; - virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; + virtual SyncOperation testSyncOperation(SyncDirection testSyncDir, bool enabled) const; virtual SyncOperation getSyncOperation() const; template <SelectedSide side> void syncTo(const FileDescriptor& descrTarget, const FileDescriptor* descrSource = NULL); //copy + update file attributes (optional) diff --git a/lib/custom_grid.cpp b/lib/custom_grid.cpp index f2892624..736bc49d 100644 --- a/lib/custom_grid.cpp +++ b/lib/custom_grid.cpp @@ -2298,13 +2298,13 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, case CustomGridMiddle::BLOCKPOS_CHECK_BOX: break; case CustomGridMiddle::BLOCKPOS_LEFT: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_LEFT)), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_LEFT, true)), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); break; case CustomGridMiddle::BLOCKPOS_MIDDLE: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_NONE)), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_NONE, true)), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); break; case CustomGridMiddle::BLOCKPOS_RIGHT: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_RIGHT)), rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_RIGHT, true)), rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); break; } else //default diff --git a/lib/parse_plural.h b/lib/parse_plural.h index 960172fa..4ac9e47b 100644 --- a/lib/parse_plural.h +++ b/lib/parse_plural.h @@ -229,7 +229,7 @@ private: { public: Parser(const Wstring& phrase, //in - const Expr<int>*& expr, int& n, PluralForm::DumpList& dump) ://out + const Expr<int>*& expr, int& n, PluralForm::DumpList& dump) : //out scn(phrase), tk(scn.nextToken()), n_(n), diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp index 97c3625c..316be694 100644 --- a/ui/main_dlg.cpp +++ b/ui/main_dlg.cpp @@ -1256,10 +1256,12 @@ void MainDialog::disableAllElements(bool enableAbort) void MainDialog::enableAllElements() { + //wxGTK, yet another QOI issue: some stupid bug, keeps moving main dialog to top!! + EnableCloseButton(true); m_panelViewFilter ->Enable(); - m_bpButtonCmpConfig ->Enable(); //wxGTK bug: this line seems to move main dialog to top!!!!!!! + m_bpButtonCmpConfig ->Enable(); m_panelFilter ->Enable(); m_panelConfig ->Enable(); m_bpButtonSyncConfig ->Enable(); @@ -1762,21 +1764,21 @@ void MainDialog::OnContextRim(wxGridEvent& event) //CONTEXT_SYNC_DIR_LEFT wxMenuItem* menuItemSyncDirLeft = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Set direction:")) + wxT(" <-") + wxT("\tAlt - Left")); //Linux needs a direction, "<-", because it has no context menu icons! - menuItemSyncDirLeft->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_LEFT))); + menuItemSyncDirLeft->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_LEFT, true))); contextMenu->Append(menuItemSyncDirLeft); contextMenu->Connect(menuItemSyncDirLeft->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncDirLeft), NULL, this); //CONTEXT_SYNC_DIR_NONE wxMenuItem* menuItemSyncDirNone = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Set direction:")) + wxT(" -") + wxT("\tAlt - Up")); - menuItemSyncDirNone->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_NONE))); + menuItemSyncDirNone->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_NONE, true))); contextMenu->Append(menuItemSyncDirNone); contextMenu->Connect(menuItemSyncDirNone->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncDirNone), NULL, this); //CONTEXT_SYNC_DIR_RIGHT wxMenuItem* menuItemSyncDirRight = new wxMenuItem(contextMenu.get(), wxID_ANY, wxString(_("Set direction:")) + wxT(" ->") + wxT("\tAlt - Right")); - menuItemSyncDirRight->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_RIGHT))); + menuItemSyncDirRight->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(SYNC_DIR_RIGHT, true))); contextMenu->Append(menuItemSyncDirRight); contextMenu->Connect(menuItemSyncDirRight->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextSyncDirRight), NULL, this); diff --git a/version/version.h b/version/version.h index f029c89d..50936457 100644 --- a/version/version.h +++ b/version/version.h @@ -3,7 +3,7 @@ namespace zen { -const wchar_t currentVersion[] = L"4.3"; //internal linkage! +const wchar_t currentVersion[] = L"4.4"; //internal linkage! } #endif diff --git a/version/version.rc b/version/version.rc index 60e22b93..c5f61a95 100644 --- a/version/version.rc +++ b/version/version.rc @@ -1,2 +1,2 @@ -#define VER_FREEFILESYNC 4,3,0,0 -#define VER_FREEFILESYNC_STR "4.3\0" +#define VER_FREEFILESYNC 4,4,0,0 +#define VER_FREEFILESYNC_STR "4.4\0" diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp index 8523c633..1e44afb7 100644 --- a/zen/file_handling.cpp +++ b/zen/file_handling.cpp @@ -1001,8 +1001,10 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, ProcSym //setting privileges requires admin rights! try { - //enable privilege: required to read/write SACL information + //enable privilege: required to read/write SACL information (only) activatePrivilege(SE_SECURITY_NAME); //polling allowed... + //Note: trying to copy SACL (SACL_SECURITY_INFORMATION) may return ERROR_PRIVILEGE_NOT_HELD (1314) on Samba shares. This is not due to missing privileges! + //However, this is okay, since copying NTFS permissions doesn't make sense in this case anyway //enable privilege: required to copy owner information activatePrivilege(SE_RESTORE_NAME); @@ -1027,7 +1029,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, ProcSym DWORD bytesNeeded = 0; if (::GetFileSecurity(applyLongPathPrefix(sourceResolved).c_str(), //__in LPCTSTR lpFileName, -> long path prefix IS needed, although it is NOT mentioned on MSDN!!! OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION RequestedInformation, + DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION RequestedInformation, reinterpret_cast<PSECURITY_DESCRIPTOR>(&buffer[0]), //__out_opt PSECURITY_DESCRIPTOR pSecurityDescriptor, static_cast<DWORD>(buffer.size()), //__in DWORD nLength, &bytesNeeded)) //__out LPDWORD lpnLengthNeeded @@ -1058,7 +1060,7 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, ProcSym if (!::SetFileSecurity(applyLongPathPrefix(targetResolved).c_str(), //__in LPCTSTR lpFileName, -> long path prefix IS needed, although it is NOT mentioned on MSDN!!! OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION SecurityInformation, + DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, //__in SECURITY_INFORMATION SecurityInformation, &secDescr)) //__in PSECURITY_DESCRIPTOR pSecurityDescriptor throw FileError(_("Error copying file permissions:") + L"\n\"" + sourceResolved + L"\" ->\n\"" + targetResolved + L"\"" + L"\n\n" + getLastErrorFormatted() + L" (W)"); @@ -1396,8 +1398,8 @@ public: const Zstring& targetFile_; const bool osIsvistaOrLater_; - //there is some mixed responsibility in this class, pure read-only data and abstraction for error reporting - //however we need to keep it at one place as ::CopyFileEx() requires! + //there is mixed responsibility in this class, pure read-only data and abstraction for error reporting + //however we need to keep it together as ::CopyFileEx() requires! void reportUserException(const UInt64& bytesTransferred) { @@ -1438,32 +1440,39 @@ private: }; -DWORD CALLBACK copyCallbackInternal( - LARGE_INTEGER totalFileSize, - LARGE_INTEGER totalBytesTransferred, - LARGE_INTEGER streamSize, - LARGE_INTEGER streamBytesTransferred, - DWORD dwStreamNumber, - DWORD dwCallbackReason, - HANDLE hSourceFile, - HANDLE hDestinationFile, - LPVOID lpData) +DWORD CALLBACK copyCallbackInternal(LARGE_INTEGER totalFileSize, + LARGE_INTEGER totalBytesTransferred, + LARGE_INTEGER streamSize, + LARGE_INTEGER streamBytesTransferred, + DWORD dwStreamNumber, + DWORD dwCallbackReason, + HANDLE hSourceFile, + HANDLE hDestinationFile, + LPVOID lpData) { - //this callback is invoked for block sizes managed by Windows, these may vary from e.g. 64 kB up to 1MB. It seems this is dependent from file size amongst others. + /* + this callback is invoked for block sizes managed by Windows, these may vary from e.g. 64 kB up to 1MB. It seems this depends on file size amongst others. + + symlink handling: + if source is a symlink and COPY_FILE_COPY_SYMLINK is specified, this callback is NOT invoked! + if source is a symlink and COPY_FILE_COPY_SYMLINK is NOT specified, this callback is called and hSourceFile is a handle to the *target* of the link! - //symlink handling: - //if source is a symlink and COPY_FILE_COPY_SYMLINK is specified, this callback is NOT invoked! - //if source is a symlink and COPY_FILE_COPY_SYMLINK is NOT specified, this callback is called and hSourceFile is a handle to the *target* of the link! + file time handling: + ::CopyFileEx() will copy file modification time (only) over from source file AFTER the last inocation of this callback + => it is possible to adapt file creation time of target in here, but NOT file modification time! - //file time handling: - //::CopyFileEx() will copy file modification time (only) over from source file AFTER the last inocation of this callback - //=> it is possible to adapt file creation time of target in here, but NOT file modification time! + alternate data stream handling: + CopyFileEx() processes multiple streams one after another, stream 1 is the file data stream and always available! + Each stream is initialized with CALLBACK_STREAM_SWITCH and provides *new* hSourceFile, hDestinationFile. + Calling GetFileInformationByHandle() on hDestinationFile for stream > 1 results in ERROR_ACCESS_DENIED! + */ CallbackData& cbd = *static_cast<CallbackData*>(lpData); - //#################### return source file attributes ################################ - if (dwCallbackReason == CALLBACK_STREAM_SWITCH) //called up front for every file (even if 0-sized) + if (dwCallbackReason == CALLBACK_STREAM_SWITCH && //called up-front for every file (even if 0-sized) + dwStreamNumber == 1) //ADS! { + //#################### return source file attributes ################################ BY_HANDLE_FILE_INFORMATION fileInfoSrc = {}; if (!::GetFileInformationByHandle(hSourceFile, &fileInfoSrc)) { @@ -1480,7 +1489,7 @@ DWORD CALLBACK copyCallbackInternal( FileAttrib attr; attr.fileSize = UInt64(fileInfoSrc.nFileSizeLow, fileInfoSrc.nFileSizeHigh); - attr.modificationTime = toTimeT(fileInfoSrc.ftLastWriteTime); + attr.modificationTime = toTimeT(fileInfoSrc.ftLastWriteTime); //no DST hack (yet) attr.sourceFileId = extractFileID(fileInfoSrc); attr.targetFileId = extractFileID(fileInfoTrg); @@ -1498,18 +1507,12 @@ DWORD CALLBACK copyCallbackInternal( return PROGRESS_CANCEL; } - if (!::SetFileTime(hDestinationFile, - &creationTime, - NULL, - NULL)) - { - cbd.reportError(_("Error changing modification time:") + L"\n\"" + cbd.targetFile_ + L"\"" + L"\n\n" + getLastErrorFormatted()); - return PROGRESS_CANCEL; - } + ::SetFileTime(hDestinationFile, &creationTime, NULL, NULL); //no error handling! //############################################################################## } - //if (totalFileSize.QuadPart == totalBytesTransferred.QuadPart) {} //called after copy operation is finished - note: for 0-sized files this callback is invoked just ONCE! + //called after copy operation is finished - note: for 0-sized files this callback is invoked just ONCE! + //if (totalFileSize.QuadPart == totalBytesTransferred.QuadPart && dwStreamNumber == 1) {} if (cbd.userCallback) { @@ -1621,8 +1624,13 @@ void rawCopyWinApi_sub(const Zstring& sourceFile, *newAttrib = cbd.getSrcAttr(); { + //DST hack const Int64 modTime = getFileTime(sourceFile, SYMLINK_FOLLOW); //throw FileError setFileTime(targetFile, modTime, SYMLINK_FOLLOW); //throw FileError + + if (newAttrib) + newAttrib->modificationTime = modTime; + //note: this sequence leads to a loss of precision of up to 1 sec! //perf-loss on USB sticks with many small files of about 30%! damn! } @@ -1990,7 +1998,7 @@ void rawCopyStream(const Zstring& sourceFile, CallbackCopyFile* callback, FileAttrib* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting { - zen::ScopeGuard guardTarget = zen::makeGuard([&]() { removeFile(targetFile); }); //transactional behavior: place guard before lifetime of FileOutput + zen::ScopeGuard guardTarget = zen::makeGuard([&] { removeFile(targetFile); }); //transactional behavior: place guard before lifetime of FileOutput try { //open sourceFile for reading @@ -1999,10 +2007,13 @@ void rawCopyStream(const Zstring& sourceFile, //create targetFile and open it for writing FileOutput fileOut(targetFile, FileOutput::ACC_CREATE_NEW); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting - static boost::thread_specific_ptr<std::vector<char>> cpyBuf; + std::vector<char>& buffer = []() -> std::vector<char>& + { + static boost::thread_specific_ptr<std::vector<char>> cpyBuf; if (!cpyBuf.get()) cpyBuf.reset(new std::vector<char>(512 * 1024)); //512 kb seems to be a reasonable buffer size - std::vector<char>& buffer = *cpyBuf; + return *cpyBuf; + }(); //copy contents of sourceFile to targetFile UInt64 totalBytesTransferred; @@ -2140,21 +2151,12 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath -> higher performance on non-buffered drives (e.g. usb sticks) */ - //set file permissions + //file permissions if (copyFilePermissions) { - zen::ScopeGuard guardTargetFile = zen::makeGuard([&]() { removeFile(targetFile);}); - copyObjectPermissions(sourceFile, targetFile, SYMLINK_FOLLOW); //throw FileError - + zen::ScopeGuard guardTargetFile = zen::makeGuard([&] { removeFile(targetFile);}); - /* - warn_static("fix!!") - try - { - copyObjectPermissions(targetFile, L"kfsdaj", SYMLINK_FOLLOW); //throw FileError - } - catch (...) {} - */ + copyObjectPermissions(sourceFile, targetFile, SYMLINK_FOLLOW); //throw FileError guardTargetFile.dismiss(); //target has been created successfully! } diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp index 81e70383..8a8a8b6f 100644 --- a/zen/file_traverser.cpp +++ b/zen/file_traverser.cpp @@ -126,7 +126,7 @@ struct X //see "policy based design" { typedef ... Handle; typedef ... FindData; -static Handle create(const Zstring& directoryPf, FindData& fileInfo); //throw FileError +static Handle create(const Zstring& directoryPf, FindData& fileInfo); //throw FileError - concession to FindFirstFile(): implement two operations: 1. open handle, 2. retrieve first data set static void destroy(Handle hnd); //throw() static bool next(Handle hnd, const Zstring& directory, WIN32_FIND_DATA& fileInfo) //throw FileError |