1 #include "chmod_data.h"
2
3 #include <libfilezilla/string.hpp>
4
5 #include <cstring>
6
ConvertPermissions(std::wstring const & rwx,char * permissions)7 bool ChmodData::ConvertPermissions(std::wstring const& rwx, char* permissions)
8 {
9 if (!permissions) {
10 return false;
11 }
12
13 size_t pos = rwx.find('(');
14 if (pos != std::wstring::npos && rwx.back() == ')') {
15 // MLSD permissions:
16 // foo (0644)
17 return DoConvertPermissions(rwx.substr(pos + 1, rwx.size() - pos - 2), permissions);
18 }
19
20 return DoConvertPermissions(rwx, permissions);
21 }
22
DoConvertPermissions(std::wstring const & rwx,char * permissions)23 bool ChmodData::DoConvertPermissions(std::wstring const& rwx, char* permissions)
24 {
25 if (rwx.size() < 3) {
26 return false;
27 }
28 size_t i;
29 for (i = 0; i < rwx.size(); ++i) {
30 if (rwx[i] < '0' || rwx[i] > '9') {
31 break;
32 }
33 }
34 if (i == rwx.size()) {
35 // Mode, e.g. 0723
36 for (i = 0; i < 3; ++i) {
37 int m = rwx[rwx.size() - 3 + i] - '0';
38
39 for (int j = 0; j < 3; ++j) {
40 if (m & (4 >> j)) {
41 permissions[i * 3 + j] = 2;
42 }
43 else {
44 permissions[i * 3 + j] = 1;
45 }
46 }
47 }
48
49 return true;
50 }
51
52 unsigned char const permchars[3] = { 'r', 'w', 'x' };
53
54 if (rwx.size() != 10) {
55 return false;
56 }
57
58 for (int j = 0; j < 9; ++j) {
59 bool set = rwx[j + 1] == permchars[j % 3];
60 permissions[j] = set ? 2 : 1;
61 }
62 if (rwx[3] == 's') {
63 permissions[2] = 2;
64 }
65 if (rwx[6] == 's') {
66 permissions[5] = 2;
67 }
68 if (rwx[9] == 't') {
69 permissions[8] = 2;
70 }
71
72 return true;
73 }
74
75
GetPermissions(const char * previousPermissions,bool dir)76 std::wstring ChmodData::GetPermissions(const char* previousPermissions, bool dir)
77 {
78 // Construct a new permission string
79
80 if (numeric_.size() < 3) {
81 return numeric_;
82 }
83
84 for (size_t i = numeric_.size() - 3; i < numeric_.size(); ++i) {
85 if ((numeric_[i] < '0' || numeric_[i] > '9') && numeric_[i] != 'x') {
86 return numeric_;
87 }
88 }
89
90 if (!previousPermissions) {
91 std::wstring ret = numeric_;
92 size_t const size = ret.size();
93 if (numeric_[size - 1] == 'x') {
94 ret[size - 1] = dir ? '5' : '4';
95 }
96 if (numeric_[size - 2] == 'x') {
97 ret[size - 2] = dir ? '5' : '4';
98 }
99 if (numeric_[size - 3] == 'x') {
100 ret[size - 3] = dir ? '7' : '6';
101 }
102 // Use default of (0...0)755 for dirs and
103 // 644 for files
104 for (size_t i = 0; i < size - 3; ++i) {
105 if (numeric_[i] == 'x') {
106 ret[i] = '0';
107 }
108 }
109 return ret;
110 }
111
112 // 2 set, 1 unset, 0 keep
113
114 const char defaultPerms[9] = { 2, 2, 2, 2, 1, 2, 2, 1, 2 };
115 char perms[9];
116 memcpy(perms, permissions_, 9);
117
118 std::wstring permission = numeric_.substr(0, numeric_.size() - 3);
119 size_t k = 0;
120 for (size_t i = numeric_.size() - 3; i < numeric_.size(); ++i, ++k) {
121 for (size_t j = k * 3; j < k * 3 + 3; ++j) {
122 if (!perms[j]) {
123 if (previousPermissions[j]) {
124 perms[j] = previousPermissions[j];
125 }
126 else {
127 perms[j] = defaultPerms[j];
128 }
129 }
130 }
131 permission += fz::to_wstring((perms[k * 3] - 1) * 4 + (perms[k * 3 + 1] - 1) * 2 + (perms[k * 3 + 2] - 1) * 1);
132 }
133
134 return permission;
135 }
136