Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelfmz <fenix1905@tut.by>2022-10-29 23:04:59 +0300
committerelfmz <fenix1905@tut.by>2022-10-29 23:04:59 +0300
commit5f4ea8b9cf7eef926d32da2142eabec48936c2fc (patch)
tree4af058ec89fe3d627b8df239a9d29116303f7716
parent011b24338ab26b8d16b10b17d3f49d407907baaf (diff)
Location menu mountpoints customizations (touch #1378 #1379)
-rw-r--r--far2l/bootstrap/scripts/FarEng.hlf.m420
-rw-r--r--far2l/bootstrap/scripts/FarRus.hlf.m422
-rw-r--r--far2l/bootstrap/scripts/FarUkr.hlf.m422
-rw-r--r--far2l/bootstrap/scripts/farlang.templ.m460
-rw-r--r--far2l/src/Mounts.cpp164
-rw-r--r--far2l/src/Mounts.hpp6
-rw-r--r--far2l/src/cfg/config.cpp7
-rw-r--r--far2l/src/cfg/config.hpp17
-rw-r--r--far2l/src/execute.cpp30
-rw-r--r--far2l/src/execute_oscmd.cpp1
-rw-r--r--far2l/src/mix/MountInfo.cpp52
-rw-r--r--far2l/src/mix/MountInfo.h3
-rw-r--r--far2l/src/panel.cpp18
-rw-r--r--far2l/src/panel.hpp14
-rw-r--r--far2l/src/vt/vtcompletor.cpp1
-rw-r--r--utils/CMakeLists.txt1
-rw-r--r--utils/include/Environment.h4
-rw-r--r--utils/include/utils.h3
-rw-r--r--utils/src/Environment.cpp68
-rw-r--r--utils/src/POpen.cpp38
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;
+}