NetRocks CtrlA-3: show timestamp (read only)
[far2l.git] / NetRocks / src / Op / OpChangeMode.cpp
blob3c3ab1f7f89cfcb8b01dcd8fc4df2b94a35b01b6
1 #include "OpChangeMode.h"
2 #include <utils.h>
3 #include "../UI/Activities/ConfirmChangeMode.h"
4 #include "../UI/Activities/SimpleOperationProgress.h"
5 #include "OpGetLinkTarget.h"
6 #include "../Globals.h"
8 OpChangeMode::OpChangeMode(std::shared_ptr<IHost> &base_host, const std::string &base_dir,
9 struct PluginPanelItem *items, int items_count)
11 OpBase(0, base_host, base_dir),
12 _recurse(false),
13 _mode_set(0),
14 _mode_clear(0)
16 bool has_dirs = false;
17 mode_t mode_all = 07777, mode_any = 0;
18 for (int i = 0; i < items_count; ++i) {
19 if (items[i].FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
20 has_dirs = true;
21 /*mode_all = 0;
22 mode_any = 07777;
23 break;*/
25 mode_all&= items[i].FindData.dwUnixMode;
26 mode_any|= (items[i].FindData.dwUnixMode & 07777);
28 std::wstring owner = items[0].Owner ? items[0].Owner : G.GetMsgWide(MOwnerUnknown);
29 std::wstring group = items[0].Group ? items[0].Group : G.GetMsgWide(MGroupUnknown);
30 for (int i = 1; i < items_count; ++i) {
31 if ((items[i].Owner && owner != items[i].Owner) || (!items[i].Owner && owner != G.GetMsgWide(MOwnerUnknown))) {
32 owner = G.GetMsgWide(MOwnerMultiple);
33 break;
36 for (int i = 1; i < items_count; ++i) {
37 if ((items[i].Group && group != items[i].Group) || (!items[i].Group && group != G.GetMsgWide(MGroupUnknown))) {
38 group = G.GetMsgWide(MOwnerMultiple);
39 break;
42 std::string display_path = base_dir, link_target;
43 FILETIME ftCreationTime = {0};
44 FILETIME ftLastAccessTime = {0};
45 FILETIME ftLastWriteTime = {0};
46 if (items_count == 1) {
47 if (!display_path.empty() && display_path.back() != '/') {
48 display_path+= '/';
50 Wide2MB(items->FindData.lpwszFileName, display_path, true);
51 if (items->FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
52 if (!OpGetLinkTarget(0, base_host, base_dir, items).Do(link_target)) {
53 link_target.clear();
56 ftCreationTime = items->FindData.ftCreationTime;
57 ftLastAccessTime = items->FindData.ftLastAccessTime;
58 ftLastWriteTime = items->FindData.ftLastWriteTime;
61 if (!ConfirmChangeMode(items_count, display_path, link_target, owner, group,
62 ftCreationTime, ftLastAccessTime, ftLastWriteTime,
63 has_dirs, mode_all, mode_any).Ask(_recurse, _mode_set, _mode_clear)) {
64 throw AbortError();
67 _enumer = std::make_shared<Enumer>(_entries, _base_host, _base_dir, items, items_count, true, _state, _wea_state);
70 void OpChangeMode::Do()
72 if (!StartThread()) {
75 } else if (IS_SILENT(_op_mode)) {
76 WaitThread();
78 } else if (!WaitThread(1000)) {
79 SimpleOperationProgress p(SimpleOperationProgress::K_CHANGEMODE, _base_dir, _state);
80 p.Show();
81 WaitThread();
86 void OpChangeMode::Process()
88 _enumer->Scan(_recurse);
89 for (const auto &entry : _entries) {
90 ChangeModeOfPath(entry.first, entry.second.mode);
91 ProgressStateUpdate psu(_state);
92 // _state.path = path;
93 _state.stats.count_complete++;
97 void OpChangeMode::ChangeModeOfPath(const std::string &path, mode_t prev_mode)
99 WhatOnErrorWrap<WEK_CHMODE>(_wea_state, _state, _base_host.get(), path,
100 [&] () mutable
102 mode_t new_mode = prev_mode;
103 new_mode&= (~_mode_clear);
104 new_mode|= (_mode_set);
105 if (S_ISDIR(prev_mode)) {
106 // hacky workaround:
107 // for directories 'x' means cd-ability, so treat it allowed if if 'r' allowed
108 if (prev_mode & S_IRUSR) {
109 new_mode|= (prev_mode & S_IXUSR);
111 if (prev_mode & S_IRGRP) {
112 new_mode|= (prev_mode & S_IXGRP);
114 if (prev_mode & S_IROTH) {
115 new_mode|= (prev_mode & S_IXOTH);
118 if (new_mode != prev_mode) {
119 _base_host->SetMode(path.c_str(), new_mode & 07777);
122 // fprintf(stderr, "%o -> %o '%s'\n", prev_mode, new_mode, path.c_str());