diff --git a/far/config.cpp b/far/config.cpp index 45b7aae65a..0d890ac875 100644 --- a/far/config.cpp +++ b/far/config.cpp @@ -2015,6 +2015,7 @@ void Options::InitConfigsData() {FSSF_PRIVATE, NKeySystem, L"CmdHistoryRule"sv, CmdHistoryRule, false}, {FSSF_PRIVATE, NKeySystem, L"ConsoleDetachKey"sv, ConsoleDetachKey, L"CtrlShiftTab"sv}, {FSSF_PRIVATE, NKeySystem, L"CopyBufferSize"sv, CMOpt.BufferSize, 0}, + {FSSF_PRIVATE, NKeySystem, L"SystemCopyNoBufferingMinSize"sv, CMOpt.SystemCopyNoBufferingMinSize, 1048576}, {FSSF_SYSTEM, NKeySystem, L"CopyOpened"sv, CMOpt.CopyOpened, true}, {FSSF_PRIVATE, NKeySystem, L"CopyTimeRule"sv, CMOpt.CopyTimeRule, 3}, {FSSF_PRIVATE, NKeySystem, L"CopySecurityOptions"sv, CMOpt.CopySecurityOptions, 0}, diff --git a/far/config.hpp b/far/config.hpp index 57b56c7b17..2f61a28a80 100644 --- a/far/config.hpp +++ b/far/config.hpp @@ -741,6 +741,7 @@ class Options: noncopyable IntOption CopySecurityOptions; // для операции Move - что делать с опцией "Copy access rights" IntOption CopyTimeRule; // $ 30.01.2001 VVM Показывает время копирования,оставшееся время и среднюю скорость IntOption BufferSize; + IntOption SystemCopyNoBufferingMinSize; // минимальная длина файла для которого можно включить COPY_FILE_NO_BUFFERING }; struct DeleteOptions diff --git a/far/copy.cpp b/far/copy.cpp index 66b7506ac5..63b8d344b0 100644 --- a/far/copy.cpp +++ b/far/copy.cpp @@ -168,6 +168,7 @@ class ShellCopy : noncopyable std::unique_ptr CP; std::unique_ptr m_Filter; DWORD Flags; + DWORD SystemCopyNoBufferingMinSize; panel_ptr SrcPanel, DestPanel; panel_mode SrcPanelMode, DestPanelMode; int SrcDriveType{}, DestDriveType{}; @@ -236,6 +237,7 @@ enum COPY_FLAGS FCOPY_USESYSTEMCOPY = 10_bit, // использовать системную функцию копирования FCOPY_COPYLASTTIME = 11_bit, // При копировании в несколько каталогов устанавливается для последнего. FCOPY_UPDATEPPANEL = 12_bit, // необходимо обновить пассивную панель + FCOPY_COPY_FILE_NO_BUFFERING = 13_bit, // дополнение для системной функции копирования больших файлов }; template @@ -294,6 +296,9 @@ enum enumShellCopy IS_SC_PRESERVETIMESTAMPS, ID_SC_COPYSYMLINK, ID_SC_MULTITARGET, + ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING, + ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING_MIN_SIZE, + ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING_MIN_SIZE_TITLE, ID_SC_SEPARATOR3, ID_SC_USEFILTER, ID_SC_SEPARATOR4, @@ -645,10 +650,12 @@ ShellCopy::ShellCopy( // *********************************************************************** // *** Prepare Dialog Controls // *********************************************************************** - int DlgW = 76, DlgH = 17; + int DlgW = 76, DlgH = 17 + 1; FARDIALOGITEMFLAGS no_tree = Global->Opt->Tree.TurnOffCompletely ? DIF_HIDDEN|DIF_DISABLE : 0; + int posFix = (int)(msg(lng::MCopySystemCopyNoBuffering).length() + 9); + auto CopyDlg = MakeDialogItems( { { DI_DOUBLEBOX, {{3, 1 }, {DlgW - 4, DlgH - 2}}, DIF_NONE, msg(lng::MCopyDlgTitle), }, @@ -665,13 +672,18 @@ ShellCopy::ShellCopy( { DI_CHECKBOX, {{5, 8 }, {0, 8 }}, DIF_NONE, msg(lng::MCopyPreserveAllTimestamps), }, { DI_CHECKBOX, {{5, 9 }, {0, 9 }}, DIF_NONE, msg(lng::MCopySymLinkContents), }, { DI_CHECKBOX, {{5, 10}, {0, 10}}, DIF_NONE, msg(lng::MCopyMultiActions), }, - { DI_TEXT, {{-1, 11}, {0, 11}}, DIF_SEPARATOR, }, - { DI_CHECKBOX, {{5, 12}, {0, 12}}, DIF_AUTOMATION, msg(lng::MCopyUseFilter), }, - { DI_TEXT, {{-1, 13}, {0, 13}}, DIF_SEPARATOR, }, - { DI_BUTTON, {{0, 14}, {0, 14}}, DIF_CENTERGROUP | DIF_DEFAULTBUTTON, msg(lng::MCopyDlgCopy), }, - { DI_BUTTON, {{0, 14}, {0, 14}}, DIF_CENTERGROUP | DIF_BTNNOCLOSE | no_tree, msg(lng::MCopyDlgTree), }, - { DI_BUTTON, {{0, 14}, {0, 14}}, DIF_CENTERGROUP | DIF_BTNNOCLOSE | DIF_AUTOMATION | (m_UseFilter ? DIF_NONE : DIF_DISABLE), msg(lng::MCopySetFilter), }, - { DI_BUTTON, {{0, 14}, {0, 14}}, DIF_CENTERGROUP, msg(lng::MCopyDlgCancel), }, + + { DI_CHECKBOX, {{5, 11}, {0, 11}}, DIF_AUTOMATION, msg(lng::MCopySystemCopyNoBuffering), }, + { DI_FIXEDIT, {{posFix, 11}, {posFix + 3, 11}}, DIF_MASKEDIT | DIF_AUTOMATION | DIF_DISABLE, L""}, + { DI_TEXT, {{posFix + 5, 11}, {0, 11}}, DIF_NONE, L"MB", }, + + { DI_TEXT, {{-1, 12}, {0, 12}}, DIF_SEPARATOR, }, + { DI_CHECKBOX, {{5, 13}, {0, 13}}, DIF_AUTOMATION, msg(lng::MCopyUseFilter), }, + { DI_TEXT, {{-1, 14}, {0, 14}}, DIF_SEPARATOR, }, + { DI_BUTTON, {{0, 15}, {0, 15}}, DIF_CENTERGROUP | DIF_DEFAULTBUTTON, msg(lng::MCopyDlgCopy), }, + { DI_BUTTON, {{0, 15}, {0, 15}}, DIF_CENTERGROUP | DIF_BTNNOCLOSE | no_tree, msg(lng::MCopyDlgTree), }, + { DI_BUTTON, {{0, 15}, {0, 15}}, DIF_CENTERGROUP | DIF_BTNNOCLOSE | DIF_AUTOMATION | (m_UseFilter ? DIF_NONE : DIF_DISABLE), msg(lng::MCopySetFilter), }, + { DI_BUTTON, {{0, 15}, {0, 15}}, DIF_CENTERGROUP, msg(lng::MCopyDlgCancel), }, }); CopyDlg[ID_SC_TARGETEDIT].strHistory = L"Copy"sv; @@ -694,6 +706,18 @@ ShellCopy::ShellCopy( } } + CopyDlg[ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING].Selected = 0; + + if (!Global->Opt->CMOpt.UseSystemCopy) + { + CopyDlg[ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING].Flags |= DIF_DISABLE; + CopyDlg[ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING_MIN_SIZE_TITLE].Flags |= DIF_DISABLE; + } + + SystemCopyNoBufferingMinSize = Global->Opt->CMOpt.SystemCopyNoBufferingMinSize.Get(); + // for Dlg size in MB + CopyDlg[ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING_MIN_SIZE].strData = str(SystemCopyNoBufferingMinSize / 1048576UL); + if (Link) { CopyDlg[ID_SC_COMBOTEXT].strData=msg(lng::MLinkType); @@ -975,7 +999,8 @@ ShellCopy::ShellCopy( Dlg->SetId(Link?HardSymLinkId:(Move?(CurrentOnly?MoveCurrentOnlyFileId:MoveFilesId):(CurrentOnly?CopyCurrentOnlyFileId:CopyFilesId))); Dlg->SetPosition({ -1, -1, DlgW, DlgH }); Dlg->SetAutomation(ID_SC_USEFILTER,ID_SC_BTNFILTER,DIF_DISABLE,DIF_NONE,DIF_NONE,DIF_DISABLE); -// Dlg->Show(); + Dlg->SetAutomation(ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING, ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING_MIN_SIZE, DIF_DISABLE, DIF_NONE, DIF_NONE, DIF_DISABLE); + // Dlg->Show(); // $ 02.06.2001 IS + Проверим список целей и поднимем тревогу, если он содержит ошибки int DlgExitCode; @@ -1000,6 +1025,16 @@ ShellCopy::ShellCopy( Global->Opt->CMOpt.PreserveTimestamps = CopyDlg[IS_SC_PRESERVETIMESTAMPS].Selected == BSTATE_CHECKED; + if (CopyDlg[ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING].Selected == BSTATE_CHECKED) + { + if (Global->Opt->CMOpt.SystemCopyNoBufferingMinSize.TryParse(CopyDlg[ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING_MIN_SIZE].strData)) + { + // from Dlg size in MB + SystemCopyNoBufferingMinSize = Global->Opt->CMOpt.SystemCopyNoBufferingMinSize.Get() * 1048576UL; + Global->Opt->CMOpt.SystemCopyNoBufferingMinSize.Set(SystemCopyNoBufferingMinSize); + } + } + if(!Move) { Global->Opt->CMOpt.MultiCopy=CopyDlg[ID_SC_MULTITARGET].Selected == BSTATE_CHECKED; @@ -1144,6 +1179,7 @@ ShellCopy::ShellCopy( } Flags|=CopyDlg[ID_SC_COPYSYMLINK].Selected? FCOPY_COPYSYMLINKCONTENTS : FCOPY_NONE; + Flags|= CopyDlg[ID_SC_SYSTEM_COPY_FILE_NO_BUFFERING].Selected? FCOPY_COPY_FILE_NO_BUFFERING : FCOPY_NONE; if (DestPlugin && CopyDlg[ID_SC_TARGETEDIT].strData == strInitDestDir) { @@ -3327,7 +3363,14 @@ bool ShellCopy::ShellSystemCopy(const string_view SrcName, const string_view Des const auto sd = GetSecurity(SrcName); - if (!os::fs::copy_file(SrcName, DestName, callback, {}, Flags & FCOPY_DECRYPTED_DESTINATION? COPY_FILE_ALLOW_DECRYPTED_DESTINATION : 0)) + auto copyFlags = Flags & FCOPY_DECRYPTED_DESTINATION ? COPY_FILE_ALLOW_DECRYPTED_DESTINATION : 0; + + if (Flags & FCOPY_COPY_FILE_NO_BUFFERING && SrcData.FileSize >= SystemCopyNoBufferingMinSize) + { + copyFlags |= COPY_FILE_NO_BUFFERING; + } + + if (!os::fs::copy_file(SrcName, DestName, callback, {}, copyFlags)) { rethrow_if(ExceptionPtr); Flags&=~FCOPY_DECRYPTED_DESTINATION; diff --git a/far/farlang.templ.m4 b/far/farlang.templ.m4 index f8b421dad0..3d76a3af8e 100644 --- a/far/farlang.templ.m4 +++ b/far/farlang.templ.m4 @@ -4651,6 +4651,20 @@ MCopyMultiActions "Апр&ацоўваць некалькі імёнаў файлаў" upd:"Process &multiple destinations" +MCopySystemCopyNoBuffering +"Обход &системного кэша для больших файлов" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +"Bypass &system cache for large files:" +upd:"Bypass &system cache for large files:" + MCopyDlgCopy "&Копировать" "&Copy" diff --git a/far/platform.fs.cpp b/far/platform.fs.cpp index 00f5bd74bc..a8e0b05063 100644 --- a/far/platform.fs.cpp +++ b/far/platform.fs.cpp @@ -1941,6 +1941,12 @@ namespace os::fs return false; } + if (LastError.NtError == STATUS_INVALID_PARAMETER) + { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + if (ElevationRequired(ELEVATION_MODIFY_REQUEST)) //BUGBUG, really unknown return elevation::instance().copy_file(strFrom, strTo, RoutinePtr, DataPtr, Cancel, CopyFlags);