diff options
-rw-r--r-- | far2l/bootstrap/scripts/FarEng.hlf.m4 | 20 | ||||
-rw-r--r-- | far2l/bootstrap/scripts/FarRus.hlf.m4 | 22 | ||||
-rw-r--r-- | far2l/bootstrap/scripts/FarUkr.hlf.m4 | 22 | ||||
-rw-r--r-- | far2l/bootstrap/scripts/farlang.templ.m4 | 60 | ||||
-rw-r--r-- | far2l/src/Mounts.cpp | 164 | ||||
-rw-r--r-- | far2l/src/Mounts.hpp | 6 | ||||
-rw-r--r-- | far2l/src/cfg/config.cpp | 7 | ||||
-rw-r--r-- | far2l/src/cfg/config.hpp | 17 | ||||
-rw-r--r-- | far2l/src/execute.cpp | 30 | ||||
-rw-r--r-- | far2l/src/execute_oscmd.cpp | 1 | ||||
-rw-r--r-- | far2l/src/mix/MountInfo.cpp | 52 | ||||
-rw-r--r-- | far2l/src/mix/MountInfo.h | 3 | ||||
-rw-r--r-- | far2l/src/panel.cpp | 18 | ||||
-rw-r--r-- | far2l/src/panel.hpp | 14 | ||||
-rw-r--r-- | far2l/src/vt/vtcompletor.cpp | 1 | ||||
-rw-r--r-- | utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | utils/include/Environment.h | 4 | ||||
-rw-r--r-- | utils/include/utils.h | 3 | ||||
-rw-r--r-- | utils/src/Environment.cpp | 68 | ||||
-rw-r--r-- | utils/src/POpen.cpp | 38 |
20 files changed, 397 insertions, 154 deletions
diff --git a/far2l/bootstrap/scripts/FarEng.hlf.m4 b/far2l/bootstrap/scripts/FarEng.hlf.m4 index a34fa5f4..e6f80eaf 100644 --- a/far2l/bootstrap/scripts/FarEng.hlf.m4 +++ b/far2l/bootstrap/scripts/FarEng.hlf.m4 @@ -4246,6 +4246,26 @@ $ #Macro command: hotkeys# assign a macro command to such key combination, select it from the dropdown list. +@ChangeLocationConfig +$ #Change location configuration# + Here you can choose specific kind of items to be included in change location +menu: #mountpoints#, #bookmarks# and #plugins#. + Also you can customize mountpoints items by specifing wildcards exceptions +and changing templates of what should be included into additional columns. + Following abbreviations can be used there: + #$T# - total disk space + #$U# - used disk space + #$F# - free disk space + #$A# - disk space available for non-priviledged user + #$u# - percents space used of total + #$f# - percents space free of total + #$a# - percents space available of total + #$N# - filesystem name + #$D# - device from which filesystem is mounted + #$S# - filesystem status, single character that can be + ! - for readonly FS + ? - for erroring/unresponsive FS + <space> - for normally mounted and accessible FS @KeyMacroRecPlay $ #Macro command: recording and playing-back# diff --git a/far2l/bootstrap/scripts/FarRus.hlf.m4 b/far2l/bootstrap/scripts/FarRus.hlf.m4 index daecf846..8b519880 100644 --- a/far2l/bootstrap/scripts/FarRus.hlf.m4 +++ b/far2l/bootstrap/scripts/FarRus.hlf.m4 @@ -4395,6 +4395,28 @@ $ #Макросы: кнопки назначения# комбинаций клавиш, выберите её из выпадающего списка. +@ChangeLocationConfig +$ #Настройки меню перехода# + Здесь вы можете выбрать какие виды объектов должны быть добавлены в меню +перехода: #точки монтирования#, #закладки# и #плагины#. + Так же можно настроить список точек монтирования указанием шаблонов исключений +и изменением шаблонов определяющий содержимое дополнительных колонок. + Там могут быть использованы следующие сокращения: + #$T# - полный размер диска + #$U# - использованное место на диске + #$F# - свободное место на диске + #$A# - место доступное не привилегированному пользователю + #$u# - проценты использованного места + #$f# - проценты свободного места + #$a# - проценты доступного места + #$N# - название файловой системы + #$D# - устройство на котором расположена файловая система + #$S# - один символ, обозначающий статус файловой системы: + ! - ФС доступна только для чтения + ? - ФС недоступна изза ошибки или таймаута + <пробел> - ФС полностью доступна + + @KeyMacroRecPlay $ #Макросы: запись и воспроизведение# FAR2L может выполнять ~макросы~@KeyMacro@ в двух основных режимах: diff --git a/far2l/bootstrap/scripts/FarUkr.hlf.m4 b/far2l/bootstrap/scripts/FarUkr.hlf.m4 index 66752cc0..c4fc093b 100644 --- a/far2l/bootstrap/scripts/FarUkr.hlf.m4 +++ b/far2l/bootstrap/scripts/FarUkr.hlf.m4 @@ -4397,6 +4397,28 @@ $ #Макроси: кнопки призначення# комбінацій клавіш, виберіть її зі списку. +@ChangeLocationConfig +$ #Change location configuration# + Here you can choose specific kind of items to be included in change location +menu: #mountpoints#, #bookmarks# and #plugins#. + Also you can customize mountpoints items by specifing wildcards exceptions +and changing templates of what should be included into additional columns. + Following abbreviations can be used there: + #$T# - total disk space + #$U# - used disk space + #$F# - free disk space + #$A# - disk space available for non-priviledged user + #$u# - percents space used of total + #$f# - percents space free of total + #$a# - percents space available of total + #$N# - filesystem name + #$D# - device from which filesystem is mounted + #$S# - filesystem status, single character that can be + ! - for readonly FS + ? - for erroring/unresponsive FS + <space> - for normally mounted and accessible FS + + @KeyMacroRecPlay $ #Макроси: запис та відтворення# FAR2L може виконувати ~макроси~@KeyMacro@ у двох основних режимах: diff --git a/far2l/bootstrap/scripts/farlang.templ.m4 b/far2l/bootstrap/scripts/farlang.templ.m4 index 77fcb1df..2c26f577 100644 --- a/far2l/bootstrap/scripts/farlang.templ.m4 +++ b/far2l/bootstrap/scripts/farlang.templ.m4 @@ -13428,12 +13428,12 @@ ChangeCouldNotEjectMedia "Неможливо вилучити диск із приводу %c:" ChangeDriveConfigure -"Настройка меню выбора диска" -"Change Drive Menu Options" -upd:"Change Drive Menu Options" -upd:"Change Drive Menu Options" -upd:"Change Drive Menu Options" -upd:"Change Drive Menu Options" +"Настройки меню перехода" +"Location Menu Options" +upd:"Location Menu Options" +upd:"Location Menu Options" +upd:"Location Menu Options" +upd:"Location Menu Options" "Cambiar opciones de menú de unidades" "Налаштування меню вибору диска" @@ -13527,15 +13527,15 @@ upd:"Show &bookmarks" upd:"Mostrar &bookmarks" "Показувати &закладки" -ChangeDriveShowCD -"Показывать параметры &компакт-дисков" -"Show &CD drive parameters" -upd:"Show &CD drive parameters" -upd:"Show &CD drive parameters" -upd:"Show &CD drive parameters" -upd:"Show &CD drive parameters" -"Mostrar parámetros unidad de &CD" -"Показувати параметри &компакт-дисків" +ChangeDriveShowMounts +"Показывать точки &монтирования" +"Show &mountpoints" +upd:"Show &mountpoints" +upd:"Show &mountpoints" +upd:"Show &mountpoints" +upd:"Show &mountpoints" +upd:"Show &mountpoints" +upd:"Show &mountpoints" ChangeDriveShowNetworkDrive "Показывать параметры се&тевых дисков" @@ -13557,6 +13557,36 @@ ChangeDriveMenuFooter "Ins,Del,Shift-Del,F4,F9" "Ins,Del,Shift-Del,F4,F9" +ChangeDriveExceptions +"Исключения: " +upd:"Exceptions: " +upd:"Exceptions: " +upd:"Exceptions: " +upd:"Exceptions: " +upd:"Exceptions: " +upd:"Exceptions: " +upd:"Exceptions: " + +ChangeDriveColumn2 +"Вторая колонка:" +upd:"Second column:" +upd:"Second column:" +upd:"Second column:" +upd:"Second column:" +upd:"Second column:" +upd:"Second column:" +upd:"Second column:" + +ChangeDriveColumn3 +"Третья колонка:" +upd:"Third column: " +upd:"Third column: " +upd:"Third column: " +upd:"Third column: " +upd:"Third column: " +upd:"Third column: " +upd:"Third column: " + EditControlHistoryFooter "Up/Down,Enter,Esc,Shift-Del" "Up/Down,Enter,Esc,Shift-Del" diff --git a/far2l/src/Mounts.cpp b/far2l/src/Mounts.cpp index 2804f915..7e890117 100644 --- a/far2l/src/Mounts.cpp +++ b/far2l/src/Mounts.cpp @@ -1,6 +1,7 @@ #include "headers.hpp" #include <crc64.h> +#include <wordexp.h> #include <fstream> #include "Mounts.hpp" #include "lang.hpp" @@ -64,31 +65,93 @@ namespace Mounts Enum::Enum(FARString &another_curdir) { - MountInfo mi(true); - bool has_rootfs = false; + if (Opt.ChangeDriveMode & DRIVE_SHOW_MOUNTS) + { + AddMounts(has_rootfs); + } + AddFavorites(has_rootfs); + + if (!has_rootfs) { + emplace(begin(), Entry(L"/", Msg::MountsRoot, false, ID_ROOT)); + } + + emplace(begin(), Entry( GetMyHome(), Msg::MountsHome, false, ID_HOME)); + emplace(begin(), Entry( another_curdir, Msg::MountsOther, false, ID_ANOTHER)); + + ConfigReader cfg_reader(HOTKEYS_SECTION); + for (auto &m : *this) { + if (max_path < m.path.GetLength()) + max_path = m.path.GetLength(); + if (max_info < m.info.GetLength()) + max_info = m.info.GetLength(); + if (max_usage < m.usage.GetLength()) + max_usage = m.usage.GetLength(); + wchar_t def_hk[] = {DefaultHotKey(m.id, m.path), 0}; + auto hk = cfg_reader.GetString(SettingsKey(m.id), def_hk); + m.hotkey = hk.IsEmpty() ? 0 : *hk.CPtr(); + } + } + + static void ExpandMountpointInfo(const Mountpoint &mp, FARString &str) + { + FARString val = L" "; + if (mp.bad) { + val = L"?"; + } else if (mp.read_only) { + val = L"!"; + } + ReplaceStrings(str, L"$S", val); + + FileSizeToStr(val, mp.total, -1, COLUMN_ECONOMIC | COLUMN_FLOATSIZE | COLUMN_SHOWBYTESINDEX); + ReplaceStrings(str, L"$T", val); + + FileSizeToStr(val, mp.avail, -1, COLUMN_ECONOMIC | COLUMN_FLOATSIZE | COLUMN_SHOWBYTESINDEX); + ReplaceStrings(str, L"$A", val); + + FileSizeToStr(val, mp.freee, -1, COLUMN_ECONOMIC | COLUMN_FLOATSIZE | COLUMN_SHOWBYTESINDEX); + ReplaceStrings(str, L"$F", val); + + FileSizeToStr(val, mp.total - mp.freee, -1, COLUMN_ECONOMIC | COLUMN_FLOATSIZE | COLUMN_SHOWBYTESINDEX); + ReplaceStrings(str, L"$U", val); + + if (mp.total) + val.Format(L"%d", (mp.avail * 100) / mp.total); + else + val = L"NA"; + ReplaceStrings(str, L"$a", val); + + if (mp.total) + val.Format(L"%d", (mp.freee * 100) / mp.total); + else + val = L"NA"; + ReplaceStrings(str, L"$f", val); + + if (mp.total) + val.Format(L"%d", ((mp.total - mp.freee) * 100) / mp.total); + else + val = L"NA"; + ReplaceStrings(str, L"$u", val); + + val = mp.filesystem; + ReplaceStrings(str, L"$N", val); + + val = mp.device; + ReplaceStrings(str, L"$D", val); + } + + void Enum::AddMounts(bool &has_rootfs) + { + MountInfo mi(true); for (const auto &mp : mi.Enum()) { emplace_back(); auto &e = back(); e.path = mp.path; - e.info = mp.filesystem; - if (mp.bad) { - e.usage = Opt.NoGraphics ? L"X_X" : L"❌_❌"; - - } else { - FileSizeToStr(e.usage, mp.avail, -1, COLUMN_ECONOMIC | COLUMN_FLOATSIZE | COLUMN_SHOWBYTESINDEX); //COLUMN_AUTOSIZE | COLUMN_SHOWBYTESINDEX - while (e.usage.GetLength() < 4) { - e.usage.Insert(0, L' '); - } - FARString tmp; - FileSizeToStr(tmp, mp.total, -1, COLUMN_ECONOMIC | COLUMN_FLOATSIZE | COLUMN_SHOWBYTESINDEX); //COLUMN_AUTOSIZE | COLUMN_SHOWBYTESINDEX - while (e.usage.GetLength() < 4) { - tmp.Insert(0, L' '); - } - e.usage+= L"/"; - e.usage+= tmp; - } - + e.usage = Opt.ChangeDriveColumn2; + e.info = Opt.ChangeDriveColumn3; + ExpandMountpointInfo(mp, e.usage); + ExpandMountpointInfo(mp, e.info); + if (e.path == L"/") { has_rootfs = true; } else { @@ -96,7 +159,10 @@ namespace Mounts } e.id = GenerateIdFromPath(e.path); } + } + void Enum::AddFavorites(bool &has_rootfs) + { std::ifstream favis(InMyConfig("favorites")); if (favis.is_open()) { std::string line; @@ -105,49 +171,35 @@ namespace Mounts if (line.empty() || line.front() == '#') { continue; } - std::vector<std::string> parts; - StrExplode(parts, line, "\t"); - if (!parts.empty()) { - emplace_back(); - auto &e = back(); - e.path = parts.front(); - if (parts.size() > 1) { - e.info = parts.back(); - if (parts.size() > 2) { - e.usage = parts[1]; + Environment::ExpandString(line, true, true); + std::vector<std::string> sublines; + StrExplode(sublines, line, "\n"); + for (const auto &subline : sublines) { + std::vector<std::string> parts; + StrExplode(parts, subline, "\t"); + if (!parts.empty()) { + emplace_back(); + auto &e = back(); + e.path = parts.front(); + if (parts.size() > 1) { + e.info = parts.back(); + if (parts.size() > 2) { + e.usage = parts[1]; + } } - } - e.id = GenerateIdFromPath(e.path); - if (e.path == L"/") { - has_rootfs = true; + e.id = GenerateIdFromPath(e.path); + if (e.path == L"/") { + has_rootfs = true; - } else if (*e.path.CPtr() == L'/') { - e.unmountable = true; + } else if (*e.path.CPtr() == L'/') { + e.unmountable = true; + } } } } } - - if (!has_rootfs) { - emplace(begin(), Entry(L"/", Msg::MountsRoot, false, ID_ROOT)); - } - - emplace(begin(), Entry( GetMyHome(), Msg::MountsHome, false, ID_HOME)); - emplace(begin(), Entry( another_curdir, Msg::MountsOther, false, ID_ANOTHER)); - - ConfigReader cfg_reader(HOTKEYS_SECTION); - for (auto &m : *this) { - if (max_path < m.path.GetLength()) - max_path = m.path.GetLength(); - if (max_info < m.info.GetLength()) - max_info = m.info.GetLength(); - if (max_usage < m.usage.GetLength()) - max_usage = m.usage.GetLength(); - wchar_t def_hk[] = {DefaultHotKey(m.id, m.path), 0}; - auto hk = cfg_reader.GetString(SettingsKey(m.id), def_hk); - m.hotkey = hk.IsEmpty() ? 0 : *hk.CPtr(); - } } + ////// bool Unmount(const FARString &path, bool force) { diff --git a/far2l/src/Mounts.hpp b/far2l/src/Mounts.hpp index 8ed2a00c..6c029cc7 100644 --- a/far2l/src/Mounts.hpp +++ b/far2l/src/Mounts.hpp @@ -23,8 +23,12 @@ namespace Mounts int id = -1; }; - struct Enum : std::vector<Entry> + class Enum : public std::vector<Entry> { + void AddMounts(bool &has_rootfs); + void AddFavorites(bool &has_rootfs); + + public: Enum(FARString &another_curdir); size_t max_path = 4; diff --git a/far2l/src/cfg/config.cpp b/far2l/src/cfg/config.cpp index 3905bfd8..bbada1c2 100644 --- a/far2l/src/cfg/config.cpp +++ b/far2l/src/cfg/config.cpp @@ -853,8 +853,13 @@ static struct FARConfig {1, REG_DWORD, NKeySystem, "InactivityExit",&Opt.InactivityExit,0, 0}, {1, REG_DWORD, NKeySystem, "InactivityExitTime",&Opt.InactivityExitTime,15, 0}, - {1, REG_DWORD, NKeySystem, "DriveMenuMode",&Opt.ChangeDriveMode,DRIVE_SHOW_TYPE|DRIVE_SHOW_PLUGINS|DRIVE_SHOW_SIZE_FLOAT|DRIVE_SHOW_BOOKMARKS, 0}, + {1, REG_DWORD, NKeySystem, "DriveMenuMode2",&Opt.ChangeDriveMode,(DWORD)-1, 0}, {1, REG_DWORD, NKeySystem, "DriveDisconnetMode",&Opt.ChangeDriveDisconnetMode,1, 0}, + + {1, REG_SZ, NKeySystem, "DriveExceptions",&Opt.ChangeDriveExceptions, 0, L"/System/*;/proc;/proc/*;/sys;/sys/*;/dev;/dev/*;/run;/run/*;/tmp;/snap;/snap/*;/private;/private/*"}, + {1, REG_SZ, NKeySystem, "DriveColumn2",&Opt.ChangeDriveColumn2, 0, L"$U/$T"}, + {1, REG_SZ, NKeySystem, "DriveColumn3",&Opt.ChangeDriveColumn3, 0, L"$S$D"}, + {1, REG_DWORD, NKeySystem, "AutoUpdateRemoteDrive",&Opt.AutoUpdateRemoteDrive,1, 0}, {1, REG_DWORD, NKeySystem, "FileSearchMode",&Opt.FindOpt.FileSearchMode,FINDAREA_FROM_CURRENT, 0}, {0, REG_DWORD, NKeySystem, "CollectFiles",&Opt.FindOpt.CollectFiles, 1, 0}, diff --git a/far2l/src/cfg/config.hpp b/far2l/src/cfg/config.hpp index bd37616b..b64cf201 100644 --- a/far2l/src/cfg/config.hpp +++ b/far2l/src/cfg/config.hpp @@ -35,6 +35,21 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FARString.hpp" +enum +{ + DRIVE_SHOW_TYPE = 0x00000001, + DRIVE_SHOW_NETNAME = 0x00000002, + DRIVE_SHOW_LABEL = 0x00000004, + DRIVE_SHOW_FILESYSTEM = 0x00000008, + DRIVE_SHOW_SIZE = 0x00000010, + DRIVE_SHOW_MOUNTS = 0x00000020, + DRIVE_SHOW_PLUGINS = 0x00000040, + DRIVE_SHOW_BOOKMARKS = 0x00000080, + DRIVE_SHOW_SIZE_FLOAT = 0x00000100, + DRIVE_SHOW_REMOTE = 0x00000200, +}; + + // +CASR_* Поведение Ctrl-Alt-Shift для AllCtrlAltShiftRule enum { @@ -424,6 +439,8 @@ struct Options int SetupArgv; // количество каталогов в ком.строке ФАРа int ChangeDriveMode; int ChangeDriveDisconnetMode; + FARString ChangeDriveExceptions; + FARString ChangeDriveColumn2, ChangeDriveColumn3; int SaveHistory; int HistoryCount; diff --git a/far2l/src/execute.cpp b/far2l/src/execute.cpp index a7ed794c..af56b175 100644 --- a/far2l/src/execute.cpp +++ b/far2l/src/execute.cpp @@ -66,7 +66,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vtshell.h" #include "InterThreadCall.hpp" #include "ScopeHelpers.h" -#include <wordexp.h> #include <set> #include <sys/wait.h> #ifdef __FreeBSD__ @@ -483,32 +482,3 @@ bool ProcessOSAliases(FARString &strStr) return false; } -bool POpen(std::vector<std::wstring> &result, const char *command) -{ - FILE *f = popen(command, "r"); - if (!f) { - perror("POpen: popen"); - return false; - } - - char buf[0x400] = { }; - while (fgets(buf, sizeof(buf)-1, f)) { - size_t l = strlen(buf); - while (l && (buf[l-1]=='\r' || buf[l-1]=='\n')) --l; - if (l) { - buf[l] = 0; - std::wstring line = MB2Wide(buf); - while (line.size() > 40) { - size_t p = line.find(L',' , 30); - if (p==std::string::npos) break; - result.emplace_back( line.substr(0, p) ); - line.erase(0, p + 1); - } - - if (!line.empty()) result.push_back( line ); - } - } - pclose(f); - return true; -} - diff --git a/far2l/src/execute_oscmd.cpp b/far2l/src/execute_oscmd.cpp index 23a9ad3b..6e25044c 100644 --- a/far2l/src/execute_oscmd.cpp +++ b/far2l/src/execute_oscmd.cpp @@ -63,7 +63,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vtlog.h" #include <vector> #include <string> -#include <wordexp.h> #include <utils.h> // diff --git a/far2l/src/mix/MountInfo.cpp b/far2l/src/mix/MountInfo.cpp index e799a93c..b04a730d 100644 --- a/far2l/src/mix/MountInfo.cpp +++ b/far2l/src/mix/MountInfo.cpp @@ -25,6 +25,7 @@ #include "MountInfo.h" #include <ScopeHelpers.h> #include <Threaded.h> +#include <config.hpp> #include <os_call.hpp> #define DISK_SPACE_QUERY_TIMEOUT_MSEC 1000 @@ -132,6 +133,8 @@ class ThreadedStatVFS : Threaded if (r == 0) { (*_mps)[_mpi].total = ((unsigned long long)s.f_blocks) * s.f_frsize; (*_mps)[_mpi].avail = ((unsigned long long)s.f_bavail) * s.f_frsize; + (*_mps)[_mpi].freee = ((unsigned long long)s.f_bfree) * s.f_frsize; + (*_mps)[_mpi].read_only = (s.f_flag & ST_RDONLY) != 0; (*_mps)[_mpi].bad = false; } return nullptr; @@ -164,21 +167,29 @@ public: } }; -static bool SkipForLocationMenu(const char *path) +class LocationsMenuExceptions { - if (StrStartsFrom(path, "/System/") - || strcmp(path, "/proc") == 0 || StrStartsFrom(path, "/proc/") - || strcmp(path, "/sys") == 0 || StrStartsFrom(path, "/sys/") - || strcmp(path, "/dev") == 0 || StrStartsFrom(path, "/dev/") - || strcmp(path, "/run") == 0 || StrStartsFrom(path, "/run/") - || strcmp(path, "/tmp") == 0 || StrStartsFrom(path, "/tmp/") - || strcmp(path, "/snap") == 0 || StrStartsFrom(path, "/snap/") - || strcmp(path, "/private") == 0 || StrStartsFrom(path, "/private/") - ) { - return true; + std::vector<std::string> _exceptions; + +public: + LocationsMenuExceptions() + { + StrExplode(_exceptions, Opt.ChangeDriveExceptions.GetMB(), ";"); + for (auto &exc : _exceptions) { + StrTrim(exc); + } } - return false; -} + + bool Match(const char *path) + { + for (const auto &exc : _exceptions) { + if (MatchWildcardICE(path, exc.c_str())) { + return true; + } + } + return false; + } +}; MountInfo::MountInfo(bool for_location_menu) { @@ -195,6 +206,7 @@ MountInfo::MountInfo(bool for_location_menu) } _mountpoints = std::make_shared<Mountpoints>(); + LocationsMenuExceptions lme; #ifdef __linux__ // manual parsing mounts file instead of using setmntent cuz later doesnt return @@ -207,7 +219,7 @@ MountInfo::MountInfo(bool for_location_menu) parts.clear(); StrExplode(parts, line, " \t"); if (parts.size() > 1 && StrStartsFrom(parts[1], "/") - && (!for_location_menu || !SkipForLocationMenu(parts[1].c_str()))) { + && (!for_location_menu || !lme.Match(parts[1].c_str()))) { bool multi_thread_friendly; if (for_location_menu) { // Location menu doesn't care about this, so dont waist time @@ -240,10 +252,11 @@ MountInfo::MountInfo(bool for_location_menu) _mountpoints->emplace_back(Mountpoint{ parts[1], parts[2], + parts[0], multi_thread_friendly, false, - 0, - 0 + false, + 0, 0, 0 }); } } @@ -258,14 +271,17 @@ MountInfo::MountInfo(bool for_location_menu) if (r > 0) { buf.resize(r); for (const auto &fs : buf) { - if (!for_location_menu || !SkipForLocationMenu(fs.f_mntonname)) { + if (!for_location_menu || !lme.Match(fs.f_mntonname)) { _mountpoints->emplace_back(Mountpoint{ fs.f_mntonname, fs.f_fstypename, + fs.f_mntfromname, true, false, + false, ((unsigned long long)fs.f_blocks) * fs.f_bsize, // unreliable due to MNT_NOWAIT - ((unsigned long long)fs.f_bavail) * fs.f_bsize // ThreadedStatVFS will set true nums + ((unsigned long long)fs.f_bavail) * fs.f_bsize, // ThreadedStatVFS will set true nums + ((unsigned long long)fs.f_bfree) * fs.f_bsize // ... }); } } diff --git a/far2l/src/mix/MountInfo.h b/far2l/src/mix/MountInfo.h index be1bc2ea..46fc0bf0 100644 --- a/far2l/src/mix/MountInfo.h +++ b/far2l/src/mix/MountInfo.h @@ -7,12 +7,15 @@ struct Mountpoint { std::string path; std::string filesystem; + std::string device; bool multi_thread_friendly; // following fields valid only if for_location_menu set to true volatile bool bad; + volatile bool read_only; volatile unsigned long long total; volatile unsigned long long avail; + volatile unsigned long long freee; }; struct Mountpoints; diff --git a/far2l/src/panel.cpp b/far2l/src/panel.cpp index 1c964632..2b3f9ef8 100644 --- a/far2l/src/panel.cpp +++ b/far2l/src/panel.cpp @@ -296,7 +296,7 @@ static void AddPluginItems(VMenu &ChDisk, int Pos) static void ConfigureChangeDriveMode() { - DialogBuilder Builder(Msg::ChangeDriveConfigure, L""); + DialogBuilder Builder(Msg::ChangeDriveConfigure, L"ChangeLocationConfig"); // Builder.AddCheckbox(Msg::ChangeDriveShowDiskType, &Opt.ChangeDriveMode, DRIVE_SHOW_TYPE); // Builder.AddCheckbox(Msg::ChangeDriveShowNetworkName, &Opt.ChangeDriveMode, DRIVE_SHOW_NETNAME); // Builder.AddCheckbox(Msg::ChangeDriveShowLabel, &Opt.ChangeDriveMode, DRIVE_SHOW_LABEL); @@ -309,6 +309,20 @@ static void ConfigureChangeDriveMode() // ShowSizeFloat->Indent(3); // Builder.LinkFlags(ShowSize, ShowSizeFloat, DIF_DISABLE); + auto *ShowMountsItem = Builder.AddCheckbox(Msg::ChangeDriveShowMounts, &Opt.ChangeDriveMode, DRIVE_SHOW_MOUNTS); + + auto *EditItem = Builder.AddEditField(&Opt.ChangeDriveExceptions,28); + Builder.LinkFlags(ShowMountsItem, EditItem, DIF_DISABLE); + Builder.AddTextBefore(EditItem, Msg::ChangeDriveExceptions); + + EditItem = Builder.AddEditField(&Opt.ChangeDriveColumn2,28); + Builder.LinkFlags(ShowMountsItem, EditItem, DIF_DISABLE); + Builder.AddTextBefore(EditItem, Msg::ChangeDriveColumn2); + + EditItem = Builder.AddEditField(&Opt.ChangeDriveColumn3,28); + Builder.LinkFlags(ShowMountsItem, EditItem, DIF_DISABLE); + Builder.AddTextBefore(EditItem, Msg::ChangeDriveColumn3); + Builder.AddCheckbox(Msg::ChangeDriveShowShortcuts, &Opt.ChangeDriveMode, DRIVE_SHOW_BOOKMARKS); Builder.AddCheckbox(Msg::ChangeDriveShowPlugins, &Opt.ChangeDriveMode, DRIVE_SHOW_PLUGINS); // Builder.AddCheckbox(Msg::ChangeDriveShowCD, &Opt.ChangeDriveMode, DRIVE_SHOW_CDROM); @@ -655,7 +669,7 @@ int Panel::ChangeDiskMenu(int Pos,int FirstCall) } case KEY_CTRL6: case KEY_RCTRL6: - Opt.ChangeDriveMode ^= DRIVE_SHOW_REMOVABLE; + Opt.ChangeDriveMode ^= DRIVE_SHOW_MOUNTS; return SelPos; case KEY_CTRL7: case KEY_RCTRL7: diff --git a/far2l/src/panel.hpp b/far2l/src/panel.hpp index c51653eb..38a8b295 100644 --- a/far2l/src/panel.hpp +++ b/far2l/src/panel.hpp @@ -86,20 +86,6 @@ enum PanelSortMode enum {VIEW_0=0,VIEW_1,VIEW_2,VIEW_3,VIEW_4,VIEW_5,VIEW_6,VIEW_7,VIEW_8,VIEW_9}; -enum -{ - DRIVE_SHOW_TYPE = 0x00000001, - DRIVE_SHOW_NETNAME = 0x00000002, - DRIVE_SHOW_LABEL = 0x00000004, - DRIVE_SHOW_FILESYSTEM = 0x00000008, - DRIVE_SHOW_SIZE = 0x00000010, - DRIVE_SHOW_REMOVABLE = 0x00000020, - DRIVE_SHOW_PLUGINS = 0x00000040, - DRIVE_SHOW_BOOKMARKS = 0x00000080, - DRIVE_SHOW_SIZE_FLOAT = 0x00000100, - DRIVE_SHOW_REMOTE = 0x00000200, -}; - enum {UPDATE_KEEP_SELECTION=1,UPDATE_SECONDARY=2,UPDATE_IGNORE_VISIBLE=4,UPDATE_DRAW_MESSAGE=8,UPDATE_CAN_BE_ANNOYING=16}; enum {NORMAL_PANEL,PLUGIN_PANEL}; diff --git a/far2l/src/vt/vtcompletor.cpp b/far2l/src/vt/vtcompletor.cpp index 5634f03c..b7396df2 100644 --- a/far2l/src/vt/vtcompletor.cpp +++ b/far2l/src/vt/vtcompletor.cpp @@ -5,7 +5,6 @@ #include <sys/stat.h> #include <sys/select.h> #include <sys/wait.h> -#include <wordexp.h> #include <algorithm> #include <stdio.h> diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 44333da9..3b12f6f3 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -30,6 +30,7 @@ set(SOURCES src/TestPath.cpp src/PipeIPC.cpp src/PathParts.cpp + src/POpen.cpp ) add_library (utils ${SOURCES}) diff --git a/utils/include/Environment.h b/utils/include/Environment.h index f34a42a1..242010fd 100644 --- a/utils/include/Environment.h +++ b/utils/include/Environment.h @@ -7,7 +7,7 @@ namespace Environment const char *GetVariable(const char *name); // performs only environment variables expansion and unescaping of only '$' character - bool ExpandString(std::string &s, bool empty_if_missing); + bool ExpandString(std::string &s, bool empty_if_missing, bool allow_exec_cmd = false); enum Quoting { QUOT_NONE, @@ -29,7 +29,7 @@ namespace Environment // performs environment variables expansion, full-featured unescaping and command line // tokenization returning vector of command-line arguments begins and ends - bool ParseCommandLine(std::string &s, Arguments &args, bool empty_if_missing); + bool ParseCommandLine(std::string &s, Arguments &args, bool empty_if_missing, bool allow_exec_cmd = false); struct ExplodeCommandLine : std::vector<std::string> { diff --git a/utils/include/utils.h b/utils/include/utils.h index cb0b7e03..4d4b3538 100644 --- a/utils/include/utils.h +++ b/utils/include/utils.h @@ -331,4 +331,7 @@ template <typename ARRAY_T, class CHAR_T> dst[i] = 0; } +bool POpen(std::string &result, const char *command); +bool POpen(std::vector<std::wstring> &result, const char *command); + #define DBGLINE fprintf(stderr, "%d %d @%s\n", getpid(), __LINE__, __FILE__) diff --git a/utils/src/Environment.cpp b/utils/src/Environment.cpp index 0a3b21ed..b08c5031 100644 --- a/utils/src/Environment.cpp +++ b/utils/src/Environment.cpp @@ -1,7 +1,7 @@ -#include "utils.h" #include <stdlib.h> #include <unistd.h> #include <string.h> +#include "utils.h" namespace Environment { @@ -75,6 +75,26 @@ static bool ReplaceVariableAt(std::string &s, return out; } +static bool RunCommand(std::string &s, + size_t start, size_t &edge, std::string cmd, bool empty_if_missing) +{ + if (!ExpandString(cmd, empty_if_missing, false)) + return false; + + std::string result; + bool out = POpen(result, cmd.c_str()); + if (!out) + return empty_if_missing; + + StrTrim(result, "\r\n"); + // expand resulting stuff without commands execution for security + if (!ExpandString(result, empty_if_missing, false)) + return false; + + ReplaceSubstringAt(s, start, edge, result); + return true; +} + static void UnescapeCLikeSequence(std::string &s, size_t &i) { // check {s[i - 1]=\, s[i]=..} for sequence encoded by EscapeLikeInC and reverse that encoding @@ -130,7 +150,7 @@ static void UnescapeCLikeSequence(std::string &s, size_t &i) } // nasty and allmighty function that actually implements ExpandString and ParseCommandLine -static bool ExpandStringOrParseCommandLine(std::string &s, Arguments *args, bool empty_if_missing) +static bool ExpandStringOrParseCommandLine(std::string &s, Arguments *args, bool empty_if_missing, bool allow_exec_cmd) { // Input example: ~/${EXPANDEDFOO}/$EXPANDEDBAR/unexpanded/part if (s.empty()) { @@ -143,6 +163,7 @@ static bool ExpandStringOrParseCommandLine(std::string &s, Arguments *args, bool ENV_NONE, ENV_SIMPLE, ENV_CURLED, + ENV_COMMAND } env_state = ENV_NONE; Quoting quot = QUOT_NONE; @@ -151,8 +172,8 @@ static bool ExpandStringOrParseCommandLine(std::string &s, Arguments *args, bool bool token_splitter = true; size_t i, orig_i, env_start; - for (i = orig_i = env_start = 0; i < s.size(); ++i, ++orig_i) { - if (args && env_state == ENV_NONE && !escaping_state) { + for (i = orig_i = env_start = 0; i <= s.size(); ++i, ++orig_i) { + if (i != s.size() && args && env_state == ENV_NONE && !escaping_state) { // Check for operation and if so - grab it into dedicated token. Examples: // foo&bar -> 'foo' '&' 'bar' // foo & bar -> 'foo' '&' 'bar' @@ -175,7 +196,7 @@ static bool ExpandStringOrParseCommandLine(std::string &s, Arguments *args, bool } } - if (token_splitter && s[i] != ' ') { + if (i != s.size() && token_splitter && s[i] != ' ') { token_splitter = false; if (args) { args->emplace_back(Argument{i, 0, orig_i, 0, QUOT_NONE}); @@ -191,20 +212,37 @@ static bool ExpandStringOrParseCommandLine(std::string &s, Arguments *args, bool } if (env_state == ENV_SIMPLE) { - if (!isalnum(s[i]) && s[i] != '_') { + if (i == s.size() || (!isalnum(s[i]) && s[i] != '_')) { if (!ReplaceVariableAt(s, env_start, i, s.substr(env_start + 1, i - env_start - 1), empty_if_missing)) { out = false; } env_state = ENV_NONE; } + } + + if (i == s.size()) { + break; + } - } else if (env_state == ENV_CURLED && s[i] == '}') { + if (env_state == ENV_CURLED && s[i] == '}') { ++i; if (!ReplaceVariableAt(s, env_start, i, s.substr(env_start + 2, i - env_start - 3), empty_if_missing)) { out = false; } --i; env_state = ENV_NONE; + + } else if (env_state == ENV_COMMAND && s[i] == ')') { + ++i; + if (!allow_exec_cmd) { + if (!empty_if_missing) { + out = false; + } + } else if (!RunCommand(s, env_start, i, s.substr(env_start + 2, i - env_start - 3), empty_if_missing)) { + out = false; + } + --i; + env_state = ENV_NONE; } if (quot == QUOT_SINGLE) { @@ -255,7 +293,11 @@ static bool ExpandStringOrParseCommandLine(std::string &s, Arguments *args, bool } break; case '$': if (env_state == ENV_NONE && i + 1 < s.size()) { - if (i + 2 < s.size() && s[i + 1] == '{') { + if (i + 2 < s.size() && s[i + 1] == '(') { + env_state = ENV_COMMAND; + env_start = i; + + } else if (i + 2 < s.size() && s[i + 1] == '{') { env_state = ENV_CURLED; env_start = i; @@ -287,14 +329,14 @@ static bool ExpandStringOrParseCommandLine(std::string &s, Arguments *args, bool } -bool ExpandString(std::string &s, bool empty_if_missing) +bool ExpandString(std::string &s, bool empty_if_missing, bool allow_exec_cmd) { - return ExpandStringOrParseCommandLine(s, nullptr, empty_if_missing); + return ExpandStringOrParseCommandLine(s, nullptr, empty_if_missing, allow_exec_cmd); } -bool ParseCommandLine(std::string &s, Arguments &args, bool empty_if_missing) +bool ParseCommandLine(std::string &s, Arguments &args, bool empty_if_missing, bool allow_exec_cmd) { - return ExpandStringOrParseCommandLine(s, &args, empty_if_missing); + return ExpandStringOrParseCommandLine(s, &args, empty_if_missing, allow_exec_cmd); } /// @@ -314,7 +356,7 @@ ExplodeCommandLine::ExplodeCommandLine(const std::string &expression) void ExplodeCommandLine::Parse(std::string expression) { Arguments args; - ExpandStringOrParseCommandLine(expression, &args, false); + ExpandStringOrParseCommandLine(expression, &args, false, false); for (const auto &token : args) { emplace_back(expression.substr(token.begin, token.len)); } diff --git a/utils/src/POpen.cpp b/utils/src/POpen.cpp new file mode 100644 index 00000000..ec44d46c --- /dev/null +++ b/utils/src/POpen.cpp @@ -0,0 +1,38 @@ +#include <stdio.h> +#include <string> +#include <vector> +#include <utils.h> + +bool POpen(std::string &result, const char *command) +{ + FILE *f = popen(command, "r"); + if (!f) { + perror("POpen: popen"); + return false; + } + + char buf[0x400] = { }; + while (fgets(buf, sizeof(buf)-1, f)) { + result+= buf; + } + pclose(f); + return true; +} + +bool POpen(std::vector<std::wstring> &result, const char *command) +{ + std::string tmp; + bool out = POpen(tmp, command); + + for (size_t i = 0, ii = 0; i <= tmp.size(); ++i) { + if (i == tmp.size() || tmp[i] == '\r' || tmp[i] == '\n') { + if (i > ii) { + result.emplace_back(); + StrMB2Wide(tmp.substr(ii, i - ii), result.back()); + } + ii = i + 1; + } + } + + return out; +} |