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-27 21:41:43 +0300
committerelfmz <fenix1905@tut.by>2022-10-27 22:50:25 +0300
commit6cae1adec50281fa695649f01f682189a1ec9234 (patch)
treee90b38adb9b31216b442f67635d278b531c7cdc3
parentecefbdfc83366ac6d119e8356901ecfeb70afa7c (diff)
use MountInfo for Location menu (touch #1375)
-rwxr-xr-xfar2l/bootstrap/mounts.sh171
-rw-r--r--far2l/src/Mounts.cpp86
-rw-r--r--far2l/src/farwinapi.cpp2
-rw-r--r--far2l/src/findfile.cpp2
-rw-r--r--far2l/src/mix/MountInfo.cpp99
-rw-r--r--far2l/src/mix/MountInfo.h22
-rw-r--r--far2l/src/mix/dirmix.cpp4
-rw-r--r--far2l/src/mix/strmix.cpp9
-rw-r--r--utils/src/Threaded.cpp22
9 files changed, 164 insertions, 253 deletions
diff --git a/far2l/bootstrap/mounts.sh b/far2l/bootstrap/mounts.sh
deleted file mode 100755
index 561f5d95..00000000
--- a/far2l/bootstrap/mounts.sh
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/bin/sh
-
-##########################################################
-#This script used during FAR's Alt+F1/Alt+F2 menu building
-#---------------------------------------------------------
-# Mode of operation controlled by $1 and can be one of: 'enum' 'umount'
-# Other arguments and output depend on mode operation:
-# $1 == 'enum' - enumerates all locations
-# Outputs multiple lines with format:
-# Path1<TAB>Info1
-# Path2<TAB>Info2
-# FAR extracts path, replaces TABs with vertical lines and
-# adds resulting strings to menu
-#---------------------------------------------------------
-# $1 == 'umount' - unmounts given location
-# $2 - path to unmount
-# $3 - optional 'force' flag
-##########################################################
-
-# Optional per-user script
-if [ -x ~/.config/far2l/mounts.sh ]; then
-. ~/.config/far2l/mounts.sh
-fi
-
-##########################################################
-# This optional file may contain per-user extra values added to df output,
-# its content must be looking like:
-#path1<TAB>info1
-#path2<TAB>info2
-#-<TAB>separator_label
-#path3<TAB>info3
-FAVORITES=~/.config/far2l/favorites
-
-##########################################################
-if [ "$1" = 'umount' ]; then
- if [ "$3" = 'force' ]; then
- sudo umount -f "$2"
- else
- umount "$2"
- fi
-
-##########################################################
-else
- sysname="$(uname)"
- timeout_coreutils="false"
- column_bsdmainutils="false"
- awk_busybox="false"
- if [ "$sysname" = "Linux" ]; then
- timeout_coreutils="$(sh -c 'timeout --version > /dev/null 2>&1 && printf true || printf false')"
- column_bsdmainutils="$(sh -c 'column -h > /dev/null 2>&1 && printf true || printf false')"
- awk_busybox="$([ .$(awk 2>&1 | head -n 1 | cut -d' ' -f1) = .BusyBox ] > /dev/null 2>&1 && printf true || printf false)"
- fi
- if [ "$sysname" = "Linux" ] || [ "$sysname" = "FreeBSD" ]; then
- DF_ARGS='-T'
- DF_AVAIL=5
- DF_TOTAL=3
- DF_NAME=2
- DF_DIVBY=1
- DF_USE=6
- MNT_FS=1
- MNT_PATH=3
- FT_IDX=1
- FT_FS=3
- FT_TYPE=4
- FT_PATH=5
- TIMEOUT=1
- MNT_TYPE=0
- MNT_FILTER='cat'
- FT_HEADER='Filesystem Type 1K-blocks Used Avail Use%% Mountpoint'
- FMT_COLUMN='cat'
- if [ "$sysname" = "Linux" ]; then
- MNT_TYPE=5
- MNT_FILTER='grep -v -e " /proc\(/[\/a-z_]\+\)* " -e " /sys\(/[a-z_,]\+\)* " -e " /dev/\(pts\|hugepages\|mqueue\) " -e " /run/user/\([0-1]\+\)/doc " -e "/home/\([a-z0-9\._]\+\)/.cache/doc" -e " /tmp/\.\([a-z0-9\._]\+\)_\([a-zA-Z0-9\._]\+\) "'
- FT_HEADER='Filesystem Type 1K-blocks Used Available Use%% Mounted_on'
- if [ "$timeout_coreutils" = "true" ]; then
- FMT_COLUMN='column -t'
- fi
- fi
- if [ "$sysname" = "FreeBSD" ]; then
- MNT_FILTER='grep -v -e " \(/[a-z]\+\)*/dev/foo "'
- FT_HEADER='Filesystem Type 1K-blocks Used Avail Capacity Mounted_on'
- fi
-
- # 1} printf $FT_HEADER and mount output
- # 2) grep - use $MNT_FILTER
- # 3) awk - output almost like df
- # 4) sed - prepare for uniq to eliminate duplicated block device names
- # 5) awk - uniq by $FT_IDX and use timeout controlled df output in subshell
- # 6) column - format final output
- if [ "$sysname" = "Linux" ] && [ "$timeout_coreutils" = "true" ]; then
- DF='( printf "'$FT_HEADER'" ; printf "\n" ; mount \
- | '$MNT_FILTER' \
- | awk '"'"'{ printf "%03.0f:",NR ; printf $'$MNT_FS' " $ " ; print $'$MNT_FS' " " $'$MNT_TYPE' " " $'$MNT_PATH' }'"'"' \
- | sed -e "s_^\([0-9]\+\):\(\/dev\/[^\ ]\+\)_000:~\\2_" \
- | awk '"'"' { if ( prev != $'$FT_IDX' ) { var = "" ; "( timeout --signal=TERM '$TIMEOUT' df '$DF_ARGS' " $'$FT_PATH' " 2> /dev/null ) | head -n 2 | tail -n 1" | getline var ; if ( var != "" ) { print var } else { print $'$FT_FS' " " $'$FT_TYPE' " [size] [used] [avail] [use] " $'$FT_PATH' } } ; prev = $'$FT_IDX' } '"'"' ) \
- | '$FMT_COLUMN''
- else
- DF='( printf "'$FT_HEADER'" ; printf "\n" ; mount \
- | '$MNT_FILTER' \
- | awk '"'"' { printf "%03.0f:",NR ; printf $'$MNT_FS' " $ " ; print $'$MNT_FS' " [type] " $'$MNT_PATH' } '"'"' \
- | sed -e "s_^\([0-9]\+\):\(\/dev\/[^\ ]\+\)_000:~\\2_" \
- | awk '"'"' { if ( prev != $'$FT_IDX' ) { var = "" ; "( ( sleep '$TIMEOUT' ; kill $$ 2> /dev/null ) & exec df '$DF_ARGS' " $'$FT_PATH' " 2> /dev/null ) | head -n 2 | tail -n 1" | getline var ; if ( var != "" ) { print var } else { print $'$FT_FS' " " $'$FT_TYPE' " [size] [used] [avail] [use] " $'$FT_PATH' } } ; prev = $'$FT_IDX' } '"'"' ) \
- | '$FMT_COLUMN''
- fi
- else
- DF_ARGS='-t'
- DF_AVAIL=4
- DF_TOTAL=2
- DF_NAME=1
- DF_DIVBY=2
- DF_USE=5
- DF='df '$DF_ARGS''
- fi
-
- #FIXME: paths that contain repeated continuos spaces
- sh -c "$DF" 2>/dev/null | awk "-F " '{
- path = $NF;
- for (n = NF - 1; n > '$DF_AVAIL' && substr(path, 1, 1) != "/"; n--) {
- path = $n" "path;
- }
-
- if ( substr(path, 1, 1) == "/" && substr(path, 1, 5) != "/run/" && substr(path, 1, 5) != "/sys/" \
- && substr(path, 1, 5) != "/dev/" && substr(path, 1, 6) != "/snap/" \
- && substr(path, 1, 8) != "/System/" && substr(path, 1, 9) != "/private/" \
- && path != "/dev" ) {
-
- avail = ($'$DF_AVAIL'+0.0) / '$DF_DIVBY';
- total = ($'$DF_TOTAL'+0.0) / '$DF_DIVBY';
-
- total_units="K";
- if (total >= 1024*1024*1024) { total_units="T" ; total/= 1024*1024*1024;}
- else if (total >= 1024*1024) { total_units="G" ; total/= 1024*1024;}
- else if (total >= 1024) { total_units="M" ; total/= 1024;}
-
- avail_units="K";
- if (avail >= 1024*1024*1024) { avail_units="T" ; avail/= 1024*1024*1024;}
- else if (avail >= 1024*1024) { avail_units="G" ; avail/= 1024*1024;}
- else if (avail >= 1024) { avail_units="M" ; avail/= 1024;}
-
- avail_ident = avail < 99.9 ? ( avail < 9.9 ? "" : "_" ) : "";
- total_ident = total < 99.9 ? ( total < 9.9 ? "" : " " ) : "";
-
- avail_fraction = avail < 10 ? 1 : 0;
- total_fraction = total < 10 ? 1 : 0;
-
- separator_symbol = "/"
-
- if ("'$awk_busybox'" == "true") {
-
- avail2 = substr((avail_ident avail ".0"), 1, 3);
- total2 = substr((total_ident total ".0"), 1, 3);
-
- print_format = "%s\t%s%s%s%s%s\t%s\n";
- printf print_format, path, avail2, avail_units, separator_symbol, total2, total_units, $'$DF_NAME';
-
- } else {
-
- print_format = "%s\t%s%.*f%s%s%s%.*f%s\t%8s\n";
- printf print_format, path, avail_ident, avail_fraction, avail, avail_units, separator_symbol, total_ident, total_fraction, total, total_units, $'$DF_NAME';
- }
- }
- }'
-
- if [ -s "$FAVORITES" ]; then
- awk "-F " '{
- if ($0 != "" && substr($0, 1, 1) != "#") {
- print $0;
- }
- }' "$FAVORITES"
- fi
-fi
diff --git a/far2l/src/Mounts.cpp b/far2l/src/Mounts.cpp
index 4eb615bb..2804f915 100644
--- a/far2l/src/Mounts.cpp
+++ b/far2l/src/Mounts.cpp
@@ -1,7 +1,7 @@
#include "headers.hpp"
#include <crc64.h>
-
+#include <fstream>
#include "Mounts.hpp"
#include "lang.hpp"
#include "keys.hpp"
@@ -16,6 +16,7 @@
#include "manager.hpp"
#include "ConfigRW.hpp"
#include "HotkeyLetterDialog.hpp"
+#include "MountInfo.h"
namespace Mounts
{
@@ -63,51 +64,68 @@ namespace Mounts
Enum::Enum(FARString &another_curdir)
{
- std::string cmd = GetMyScriptQuoted("mounts.sh");
- cmd+= " enum";
+ MountInfo mi(true);
bool has_rootfs = false;
+ 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;
+ }
- FILE *f = popen(cmd.c_str(), "r");
- if (f) {
- char buf[0x2100] = { };
- std::wstring s, tmp;
- while (fgets(buf, sizeof(buf) - 1, f)!=NULL) {
- for (;;) {
- size_t l = strlen(buf);
- if (!l) break;
- if (buf[l-1]!='\r' && buf[l-1]!='\n') break;
- buf[l-1] = 0;
+ if (e.path == L"/") {
+ has_rootfs = true;
+ } else {
+ e.unmountable = true;
+ }
+ e.id = GenerateIdFromPath(e.path);
+ }
+
+ std::ifstream favis(InMyConfig("favorites"));
+ if (favis.is_open()) {
+ std::string line;
+ while (std::getline(favis, line)) {
+ StrTrim(line, " \t\r\n");
+ if (line.empty() || line.front() == '#') {
+ continue;
}
- if (buf[0]) {
+ std::vector<std::string> parts;
+ StrExplode(parts, line, "\t");
+ if (!parts.empty()) {
emplace_back();
auto &e = back();
- e.path.Copy(&buf[0]);
- size_t t;
- if (e.path.Pos(t, L'\t')) {
- e.info = e.path.SubStr(t + 1);
- e.path.Truncate(t);
- if (e.info.Pos(t, L'\t')) {
- e.usage = e.info.SubStr(0, t);
- e.info = e.info.SubStr(t + 1);
+ 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;
- } else {
+
+ } else if (*e.path.CPtr() == L'/') {
e.unmountable = true;
}
- RemoveExternalSpaces(e.usage);
- RemoveExternalSpaces(e.info);
- e.id = GenerateIdFromPath(e.path);
}
}
- int r = pclose(f);
- if (r != 0) {
- fprintf(stderr, "Exit code %u executing '%s'\n", r, cmd.c_str());
- }
- } else {
- fprintf(stderr, "Error %u executing '%s'\n", errno, cmd.c_str());
}
if (!has_rootfs) {
@@ -133,8 +151,8 @@ namespace Mounts
bool Unmount(const FARString &path, bool force)
{
- std::string cmd = GetMyScriptQuoted("mounts.sh");
- cmd+= " umount \"";
+ std::string cmd = GetMyScriptQuoted("unmount.sh");
+ cmd+= " \"";
cmd+= EscapeCmdStr(Wide2MB(path));
cmd+= "\"";
if (force) {
diff --git a/far2l/src/farwinapi.cpp b/far2l/src/farwinapi.cpp
index 0afad4d4..64e9d254 100644
--- a/far2l/src/farwinapi.cpp
+++ b/far2l/src/farwinapi.cpp
@@ -514,7 +514,7 @@ BOOL apiGetVolumeInformation(
}
if (pFileSystemName) {
- *pFileSystemName = MountInfo(false).GetFileSystem(path);
+ *pFileSystemName = MountInfo().GetFileSystem(path);
}
return TRUE;
diff --git a/far2l/src/findfile.cpp b/far2l/src/findfile.cpp
index d27f3939..f4655733 100644
--- a/far2l/src/findfile.cpp
+++ b/far2l/src/findfile.cpp
@@ -2803,7 +2803,7 @@ public:
{
SudoClientRegion scr;
DWORD msec = GetProcessUptimeMSec();
- pMountInfo.reset(new MountInfo(false));
+ pMountInfo.reset(new MountInfo);
if (PluginMode)
{
DoPreparePluginList(hDlg);
diff --git a/far2l/src/mix/MountInfo.cpp b/far2l/src/mix/MountInfo.cpp
index a655ccfb..669cd6b5 100644
--- a/far2l/src/mix/MountInfo.cpp
+++ b/far2l/src/mix/MountInfo.cpp
@@ -20,6 +20,7 @@
#include <fstream>
#include <chrono>
#include <mutex>
+#include <atomic>
#include <condition_variable>
#include "MountInfo.h"
#include <ScopeHelpers.h>
@@ -105,14 +106,6 @@ static struct FSMagic {
/////////////////////////////////////////////////////////////////////////////////////////////
-struct Mountpoint
-{
- std::string path;
- std::string filesystem;
- bool multi_thread_friendly;
- unsigned long long total, used;
-};
-
struct Mountpoints : std::vector<Mountpoint>
{
struct Pending
@@ -123,30 +116,35 @@ struct Mountpoints : std::vector<Mountpoint>
} pending;
};
-class ThreadedStatFS : Threaded
+static std::atomic<unsigned int> s_mount_info_threads{0};
+
+class ThreadedStatVFS : Threaded
{
std::shared_ptr<Mountpoints> _mps;
size_t _mpi;
void *ThreadProc()
{
- struct statfs fs{};
- int r = statfs((*_mps)[_mpi].path.c_str(), &fs);
+ struct statvfs s = {};
+ int r = statvfs((*_mps)[_mpi].path.c_str(), &s);
if (r == 0) {
- (*_mps)[_mpi].total = fs.f_bsize * fs.f_blocks;
- (*_mps)[_mpi].used = (fs.f_bsize - fs.f_bfree) * fs.f_blocks;
+ (*_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].bad = false;
}
return nullptr;
}
public:
- ThreadedStatFS(std::shared_ptr<Mountpoints> &mps, size_t mpi)
+ ThreadedStatVFS(std::shared_ptr<Mountpoints> &mps, size_t mpi)
: _mps(mps), _mpi(mpi)
{
+ ++s_mount_info_threads;
}
- virtual ~ThreadedStatFS()
+ virtual ~ThreadedStatVFS()
{
+ --s_mount_info_threads;
std::unique_lock<std::mutex> lock(_mps->pending.mtx);
_mps->pending.cnt--;
if (_mps->pending.cnt == 0) {
@@ -158,13 +156,30 @@ public:
void Start()
{
if (!StartThread(true)) {
- fprintf(stderr, "ThreadedStatFS: can't start thread\n");
+ fprintf(stderr, "ThreadedStatVFS: can't start thread\n");
delete this;
}
}
};
-MountInfo::MountInfo(bool query_space)
+
+static bool SkipForLocationMenu(const char *path)
+{
+ 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;
+ }
+ return false;
+}
+
+MountInfo::MountInfo(bool for_location_menu)
{
// force-enable multi-threaded disk access: echo e > ~/.config/far2l/mtfs
// force-disable multi-threaded disk access: echo d > ~/.config/far2l/mtfs
@@ -178,6 +193,8 @@ MountInfo::MountInfo(bool query_space)
_mountpoints = std::make_shared<Mountpoints>();
#ifdef __linux__
+ // manual parsing mounts file instead of using setmntent cuz later doesnt return
+ // mounted device path that is needed to determine if its 'rotational'
std::ifstream is("/proc/mounts");
if (is.is_open()) {
std::string line, sys_path;
@@ -185,7 +202,8 @@ MountInfo::MountInfo(bool query_space)
while (std::getline(is, line)) {
parts.clear();
StrExplode(parts, line, " \t");
- if (parts.size() > 1 && StrStartsFrom(parts[1], "/")) {
+ if (parts.size() > 1 && StrStartsFrom(parts[1], "/")
+ && (!for_location_menu || !SkipForLocationMenu(parts[1].c_str()))) {
bool multi_thread_friendly;
if (StrStartsFrom(parts[0], "/dev/")) {
sys_path = "/sys/block/";
@@ -214,6 +232,7 @@ MountInfo::MountInfo(bool query_space)
parts[1],
parts[2],
multi_thread_friendly,
+ false,
0,
0
});
@@ -226,17 +245,20 @@ MountInfo::MountInfo(bool query_space)
int r = getfsstat(nullptr, 0, MNT_NOWAIT);
if (r > 0) {
std::vector<struct statfs> buf(r * 2 + 2);
- r = getfsstat(buf.data(), buf.size(), MNT_NOWAIT);
+ r = getfsstat(buf.data(), buf.size() * sizeof(*buf.data()), MNT_NOWAIT);
if (r > 0) {
buf.resize(r);
for (const auto &fs : buf) {
- _mountpoints->emplace_back(Mountpoint{
- fs.f_mntonname,
- fs.f_fstypename,
- true,
- fs.f_bsize * fs.f_blocks,
- (fs.f_bsize - fs.f_bfree) * fs.f_blocks
- });
+ if (!for_location_menu || !SkipForLocationMenu(fs.f_mntonname)) {
+ _mountpoints->emplace_back(Mountpoint{
+ fs.f_mntonname,
+ fs.f_fstypename,
+ true,
+ 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
+ });
+ }
}
}
}
@@ -245,17 +267,23 @@ MountInfo::MountInfo(bool query_space)
if (_mountpoints->empty()) {
fprintf(stderr, "%s: no mountpoints found\n", __FUNCTION__);
- } else if (query_space) {
+ } else if (for_location_menu) {
+ if (s_mount_info_threads != 0) {
+ fprintf(stderr, "%s: still %u old threads hanging around\n",
+ __FUNCTION__, (unsigned int)s_mount_info_threads);
+ }
for (size_t i = 0; i < _mountpoints->size(); ++i) {
try {
- (new ThreadedStatFS(_mountpoints, i))->Start();
+ (*_mountpoints)[i].bad = true;
+ (new ThreadedStatVFS(_mountpoints, i))->Start();
std::unique_lock<std::mutex> lock(_mountpoints->pending.mtx);
_mountpoints->pending.cnt++;
+
} catch (std::exception &e) {
fprintf(stderr, "%s: %s\n", __FUNCTION__, e.what());
}
}
- for (DWORD ms = 0; ms < 1000;) {
+ for (DWORD ms = 0; ;) {
std::chrono::milliseconds ms_before = std::chrono::duration_cast< std::chrono::milliseconds >
(std::chrono::steady_clock::now().time_since_epoch());
{
@@ -265,17 +293,25 @@ MountInfo::MountInfo(bool query_space)
break;
}
}
- ms+= (std::chrono::duration_cast< std::chrono::milliseconds >
+ ms+= (std::chrono::duration_cast< std::chrono::milliseconds >
(std::chrono::steady_clock::now().time_since_epoch()) - ms_before).count();
+ if (ms >= 1000) {
+ fprintf(stderr, "%s: timed out\n", __FUNCTION__);
+ break;
+ }
}
}
for (const auto &it : *_mountpoints) {
fprintf(stderr, "%s: mtf=%d spc=[%llu/%llu] fs='%s' at '%s'\n", __FUNCTION__,
- it.multi_thread_friendly, it.used, it.total, it.filesystem.c_str(), it.path.c_str());
+ it.multi_thread_friendly, it.avail, it.total, it.filesystem.c_str(), it.path.c_str());
}
}
+const std::vector<Mountpoint> &MountInfo::Enum() const
+{
+ return *_mountpoints;
+}
std::string MountInfo::GetFileSystem(const std::string &path) const
{
@@ -327,3 +363,4 @@ bool MountInfo::IsMultiThreadFriendly(const std::string &path) const
}
return out;
}
+
diff --git a/far2l/src/mix/MountInfo.h b/far2l/src/mix/MountInfo.h
index 65781245..ce4bbddd 100644
--- a/far2l/src/mix/MountInfo.h
+++ b/far2l/src/mix/MountInfo.h
@@ -3,11 +3,25 @@
#include <vector>
#include <memory>
+struct Mountpoint
+{
+ std::string path;
+ std::string filesystem;
+ bool multi_thread_friendly;
+
+ // following fields valid only if for_location_menu set to true
+ volatile bool bad;
+ volatile unsigned long long total;
+ volatile unsigned long long avail;
+};
+
struct Mountpoints;
-/* This class detects if path points to device that is best to be
+/* This class enumerates mountpoints and also provides extra information
+ * like disk sizes (if for_location_menu enabled) and also it detects
+ * if specified path points to device that is best to be
* accessed in multi-thread parallel manner, like SSD drives.
- * Currently works only under Linux, others defaulted to <true>.
+ * Later currently works only under Linux, others defaulted to <true>.
*/
class MountInfo
{
@@ -15,7 +29,9 @@ class MountInfo
char _mtfs = 0;
public:
- MountInfo(bool query_space);
+ MountInfo(bool for_location_menu = false);
+
+ const std::vector<Mountpoint> &Enum() const;
std::string GetFileSystem(const std::string &path) const;
diff --git a/far2l/src/mix/dirmix.cpp b/far2l/src/mix/dirmix.cpp
index 9439a818..08063376 100644
--- a/far2l/src/mix/dirmix.cpp
+++ b/far2l/src/mix/dirmix.cpp
@@ -248,7 +248,9 @@ void CreatePath(FARString &strPath)
std::string GetHelperPathName(const char *name)
{
std::string out = g_strFarPath.GetMB();
- out+= GOOD_SLASH;
+ if (!out.empty() && out.back() != GOOD_SLASH) {
+ out+= GOOD_SLASH;
+ }
out+= name;
struct stat s;
diff --git a/far2l/src/mix/strmix.cpp b/far2l/src/mix/strmix.cpp
index 1e422050..317f68f2 100644
--- a/far2l/src/mix/strmix.cpp
+++ b/far2l/src/mix/strmix.cpp
@@ -743,8 +743,8 @@ FARString & WINAPI FileSizeToStr(FARString &strDestStr, uint64_t Size, int Width
Sz++;
}
- strStr.Format(L"%d.%02d", (DWORD)Sz,Decimal);
- FormatNumber(strStr,strStr,2);
+ strStr.Format(L"%d.%02d", (DWORD)Sz, Decimal);
+ FormatNumber(strStr, strStr, (Economic && Sz > 9) ? 1 : 2);
}
if (IndexB>0 || ShowBytesIndex)
@@ -752,7 +752,7 @@ FARString & WINAPI FileSizeToStr(FARString &strDestStr, uint64_t Size, int Width
Width-=(Economic?1:2);
if (Width<0)
- Width=0;
+ Width=strStr.GetLength();
if (Economic)
strDestStr.Format(L"%*.*ls%1.1ls",Width,Width,strStr.CPtr(),UnitStr[IndexB][IndexDiv]);
@@ -763,6 +763,7 @@ FARString & WINAPI FileSizeToStr(FARString &strDestStr, uint64_t Size, int Width
strDestStr.Format(L"%*.*ls",Width,Width,strStr.CPtr());
return strDestStr;
+
}
if (Commas)
@@ -777,7 +778,7 @@ FARString & WINAPI FileSizeToStr(FARString &strDestStr, uint64_t Size, int Width
Width-=(Economic?1:2);
if (Width<0)
- Width=0;
+ Width=strStr.GetLength();
if (Economic)
strDestStr.Format(L"%*.*ls%1.1ls",Width,Width,strStr.CPtr(),UnitStr[0][IndexDiv]);
diff --git a/utils/src/Threaded.cpp b/utils/src/Threaded.cpp
index 7e404f1d..b23f725c 100644
--- a/utils/src/Threaded.cpp
+++ b/utils/src/Threaded.cpp
@@ -10,7 +10,7 @@
Threaded::~Threaded()
{
std::lock_guard<std::mutex> lock(_trd_mtx);
- if (!_trd_exited || !_trd_joined) {
+ if (!_self_destruct && (!_trd_exited || !_trd_joined)) {
fprintf(stderr, "~Threaded: still busy\n");
abort();
}
@@ -21,16 +21,15 @@ void *Threaded::sThreadProc(void *p)
Threaded *it = (Threaded *)p;
void *result = it->ThreadProc();
- {
+ if (it->_self_destruct) {
+ delete it;
+
+ } else {
std::lock_guard<std::mutex> lock(it->_trd_mtx);
it->_trd_exited = true;
it->_trd_cond.notify_all();
}
- if (it->_self_destruct) {
- delete it;
- }
-
return result;
}
@@ -48,12 +47,21 @@ bool Threaded::StartThread(bool self_destruct)
_trd_joined = _trd_exited = false;
_self_destruct = self_destruct;
- if (pthread_create(&_trd, NULL, &sThreadProc, this) != 0) {
+ pthread_t trd;
+ if (pthread_create(&trd, NULL, &sThreadProc, this) != 0) {
_trd_joined = _trd_exited = true;
+ _self_destruct = false;
_trd = 0;
return false;
}
+ if (self_destruct) {
+ pthread_detach(trd);
+
+ } else {
+ _trd = trd;
+ }
+
return true;
}