aboutsummaryrefslogtreecommitdiff
path: root/sfm.cpp
diff options
context:
space:
mode:
authoremmett1 <me@emmett1.my>2026-06-20 16:07:40 +0800
committeremmett1 <me@emmett1.my>2026-06-20 16:07:40 +0800
commitcd2a4dffb8347337528b5f1c9e98a54994c800d5 (patch)
treef4c63870a3a145754f5f59731b1b28bc4ec6567a /sfm.cpp
parent40e5d2815cc6cdff95751af9377ebe3ff33daf81 (diff)
downloadsfm-cd2a4dffb8347337528b5f1c9e98a54994c800d5.tar.gz
sfm-cd2a4dffb8347337528b5f1c9e98a54994c800d5.zip
added permission error messsage, fix pane line, add root message if running as rootHEADmaster
Diffstat (limited to 'sfm.cpp')
-rw-r--r--sfm.cpp72
1 files changed, 59 insertions, 13 deletions
diff --git a/sfm.cpp b/sfm.cpp
index 9913b62..f199b1f 100644
--- a/sfm.cpp
+++ b/sfm.cpp
@@ -42,6 +42,7 @@ enum {
CP_OVERLAY_TITLE,
CP_BUTTON_YES,
CP_BUTTON_NO,
+ CP_ROOT_WARN,
};
#define ATTR_DIR (COLOR_PAIR(CP_DIR) | A_BOLD)
@@ -54,6 +55,7 @@ enum {
#define ATTR_MARKER COLOR_PAIR(CP_MARKER)
#define ATTR_INFO COLOR_PAIR(CP_INFO)
#define ATTR_OVERLAY_BORDER COLOR_PAIR(CP_OVERLAY_BORDER)
+#define ATTR_ROOT_WARN (COLOR_PAIR(CP_ROOT_WARN) | A_BOLD)
// ─── Entry data ─────────────────────────────────────────────────────────────
enum class EntryType { Directory, File, Symlink };
@@ -154,6 +156,7 @@ private:
bool show_details_ = false;
bool show_preview_ = false;
bool searching_ = false;
+ bool is_root_ = false;
std::string filter_;
std::string info_msg_;
@@ -321,6 +324,7 @@ void FileManager::init_colors() {
init_pair(CP_OVERLAY_TITLE, COLOR_CYAN, -1);
init_pair(CP_BUTTON_YES, COLOR_GREEN, -1);
init_pair(CP_BUTTON_NO, COLOR_RED, -1);
+ init_pair(CP_ROOT_WARN, COLOR_RED, -1);
}
// ─── directory loading ──────────────────────────────────────────────────────
@@ -554,13 +558,22 @@ void FileManager::draw_botbar() {
right = " press ? for help ";
}
- int total = static_cast<int>(left.size() + right.size());
+ std::string root_tag = is_root_ ? "[root] " : "";
+ int total = static_cast<int>(root_tag.size() + left.size() + right.size());
int pad = cols_ - total;
if (pad < 0) pad = 0;
+ int x = 0;
+ if (is_root_) {
+ attron(ATTR_ROOT_WARN);
+ mvprintw(rows_ - 1, 0, "%s", root_tag.c_str());
+ attroff(ATTR_ROOT_WARN);
+ x = static_cast<int>(root_tag.size());
+ }
+
attron(ATTR_TOPBAR);
- mvprintw(rows_ - 1, 0, "%s", left.c_str());
- for (int i = 0; i < pad; ++i) mvaddch(rows_ - 1, static_cast<int>(left.size()) + i, ' ');
+ mvprintw(rows_ - 1, x, "%s", left.c_str());
+ for (int i = 0; i < pad; ++i) mvaddch(rows_ - 1, x + static_cast<int>(left.size()) + i, ' ');
attroff(ATTR_TOPBAR);
attron(ATTR_INFO);
@@ -711,11 +724,10 @@ void FileManager::draw_preview() {
if (!e) return;
// Draw vertical divider
- for (int r = 1; r < rows_ - 1; ++r) {
- attron(ATTR_DIVIDER);
- mvaddch(r, list_cols_, '|');
- attroff(ATTR_DIVIDER);
- }
+ attron(ATTR_DIVIDER);
+ for (int r = 1; r < rows_ - 1; ++r)
+ mvaddch(r, list_cols_, ACS_VLINE);
+ attroff(ATTR_DIVIDER);
// Clear entire preview area of previous content (stale lines from last preview)
for (int r = 1; r < rows_ - 1; ++r) {
@@ -1598,6 +1610,12 @@ void FileManager::do_help() {
void FileManager::do_rename() {
const Entry *e = get_sel();
if (!e) return;
+
+ if (access(cwd_.c_str(), W_OK) != 0) {
+ flash_msg("permission denied: " + cwd_);
+ return;
+ }
+
// Strip trailing / or @
std::string name = e->name;
if (!name.empty() && (name.back() == '/' || name.back() == '@'))
@@ -1612,11 +1630,16 @@ void FileManager::do_rename() {
if (std::rename(src.c_str(), dst.c_str()) == 0) {
load_entries();
} else {
- flash_msg("rename failed");
+ flash_msg("rename failed: " + std::string(std::strerror(errno)));
}
}
void FileManager::do_mkdir() {
+ if (access(cwd_.c_str(), W_OK) != 0) {
+ flash_msg("permission denied: " + cwd_);
+ return;
+ }
+
std::string name;
if (!read_line(name, " Directory name: ")) { need_full_redraw_ = true; return; }
if (name.empty()) { flash_msg("cancelled"); return; }
@@ -1625,11 +1648,16 @@ void FileManager::do_mkdir() {
if (fs::create_directory(path)) {
load_entries();
} else {
- flash_msg("mkdir failed");
+ flash_msg("mkdir failed: " + std::string(std::strerror(errno)));
}
}
void FileManager::do_newfile() {
+ if (access(cwd_.c_str(), W_OK) != 0) {
+ flash_msg("permission denied: " + cwd_);
+ return;
+ }
+
std::string name;
if (!read_line(name, " File name: ")) { need_full_redraw_ = true; return; }
if (name.empty()) { flash_msg("cancelled"); return; }
@@ -1640,11 +1668,16 @@ void FileManager::do_newfile() {
f.close();
load_entries();
} else {
- flash_msg("cannot create file");
+ flash_msg("cannot create file: " + std::string(std::strerror(errno)));
}
}
void FileManager::do_delete() {
+ if (access(cwd_.c_str(), W_OK) != 0) {
+ flash_msg("permission denied: " + cwd_);
+ return;
+ }
+
// Gather items to delete
std::vector<std::string> targets;
if (!selected_.empty()) {
@@ -1709,6 +1742,12 @@ void FileManager::do_delete() {
void FileManager::do_trash() {
const Entry *e = get_sel();
if (!e) return;
+
+ if (access(cwd_.c_str(), W_OK) != 0) {
+ flash_msg("permission denied: " + cwd_);
+ return;
+ }
+
std::string name = e->name;
if (!name.empty() && name.back() == '/') name.pop_back();
if (!name.empty() && name.back() == '@') name.pop_back();
@@ -1743,7 +1782,7 @@ void FileManager::do_trash() {
sel_ = std::max(0, static_cast<int>(entries_.size()) - 2);
load_entries();
} else {
- flash_msg("trash failed");
+ flash_msg("trash failed: " + std::string(std::strerror(errno)));
}
}
@@ -1805,7 +1844,7 @@ void FileManager::do_chmod_x(bool set) {
flash_msg(set ? "chmod +x: " + e->name : "chmod -x: " + e->name);
load_entries();
} else {
- flash_msg("chmod failed");
+ flash_msg("chmod failed: " + std::string(std::strerror(errno)));
}
}
@@ -2021,6 +2060,11 @@ void FileManager::do_paste() {
return;
}
+ if (access(cwd_.c_str(), W_OK) != 0) {
+ flash_msg("permission denied: " + cwd_);
+ return;
+ }
+
for (const auto &src : clipboard_paths_) {
std::string name = fs::path(src).filename().string();
std::string dst = join_path(cwd_, name);
@@ -2291,6 +2335,8 @@ void FileManager::run() {
if (can_color()) init_colors();
load_entries();
+ is_root_ = (geteuid() == 0);
+
while (true) {
draw();
int key = getch();