1 #include "OpChangeMode.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
),
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
) {
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
);
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
);
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() != '/') {
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
)) {
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
)) {
67 _enumer
= std::make_shared
<Enumer
>(_entries
, _base_host
, _base_dir
, items
, items_count
, true, _state
, _wea_state
);
70 void OpChangeMode::Do()
75 } else if (IS_SILENT(_op_mode
)) {
78 } else if (!WaitThread(1000)) {
79 SimpleOperationProgress
p(SimpleOperationProgress::K_CHANGEMODE
, _base_dir
, _state
);
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
,
102 mode_t new_mode
= prev_mode
;
103 new_mode
&= (~_mode_clear
);
104 new_mode
|= (_mode_set
);
105 if (S_ISDIR(prev_mode
)) {
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());