@cetapod/react-native-smb 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +72 -0
  3. package/ReactNativeSmb.podspec +59 -0
  4. package/cpp/ios/OnLoad.mm +24 -0
  5. package/cpp/shared/HybridSMB.cpp +324 -0
  6. package/cpp/shared/HybridSMB.hpp +102 -0
  7. package/cpp/shared/ReactNativeSmb.hpp +428 -0
  8. package/cpp/shared/connection/ContextRequest.hpp +27 -0
  9. package/cpp/shared/connection/ContextRequestQueue.cpp +85 -0
  10. package/cpp/shared/connection/ContextRequestQueue.hpp +28 -0
  11. package/cpp/shared/connection/MetadataContextLease.hpp +33 -0
  12. package/cpp/shared/connection/PoolContextHandle.cpp +35 -0
  13. package/cpp/shared/connection/PoolContextHandle.hpp +44 -0
  14. package/cpp/shared/connection/PoolSlot.cpp +73 -0
  15. package/cpp/shared/connection/PoolSlot.hpp +46 -0
  16. package/cpp/shared/connection/PoolTypes.hpp +41 -0
  17. package/cpp/shared/connection/SmbConnection.cpp +385 -0
  18. package/cpp/shared/connection/SmbConnection.hpp +93 -0
  19. package/cpp/shared/connection/SmbConnectionPool.cpp +316 -0
  20. package/cpp/shared/connection/SmbConnectionPool.hpp +84 -0
  21. package/cpp/shared/core/CancellationToken.hpp +22 -0
  22. package/cpp/shared/core/OperatorContext.hpp +24 -0
  23. package/cpp/shared/core/SmbEnums.hpp +126 -0
  24. package/cpp/shared/core/SmbTask.cpp +131 -0
  25. package/cpp/shared/core/SmbTask.hpp +52 -0
  26. package/cpp/shared/core/SmbTaskCore.cpp +222 -0
  27. package/cpp/shared/core/SmbTaskCore.hpp +107 -0
  28. package/cpp/shared/core/SmbTypes.hpp +35 -0
  29. package/cpp/shared/core/TaskObserverHub.cpp +166 -0
  30. package/cpp/shared/core/TaskObserverHub.hpp +66 -0
  31. package/cpp/shared/core/TaskSnapshotCodec.cpp +32 -0
  32. package/cpp/shared/core/TaskSnapshotCodec.hpp +41 -0
  33. package/cpp/shared/io/SmbCopyTree.hpp +114 -0
  34. package/cpp/shared/io/SmbDirScan.hpp +80 -0
  35. package/cpp/shared/io/SmbFileIO.cpp +1355 -0
  36. package/cpp/shared/io/SmbFileIO.hpp +45 -0
  37. package/cpp/shared/io/SmbPathUtil.hpp +75 -0
  38. package/cpp/shared/io/SmbSecurity.cpp +308 -0
  39. package/cpp/shared/io/SmbSecurity.hpp +32 -0
  40. package/cpp/shared/io/SmbTreeOps.hpp +112 -0
  41. package/cpp/shared/operators/Operator.hpp +35 -0
  42. package/cpp/shared/operators/OperatorBase.cpp +57 -0
  43. package/cpp/shared/operators/OperatorBase.hpp +57 -0
  44. package/cpp/shared/operators/connection/ConnectOperator.cpp +19 -0
  45. package/cpp/shared/operators/connection/ConnectOperator.hpp +22 -0
  46. package/cpp/shared/operators/connection/ConnectShareOperator.cpp +19 -0
  47. package/cpp/shared/operators/connection/ConnectShareOperator.hpp +21 -0
  48. package/cpp/shared/operators/connection/DisconnectOperator.cpp +12 -0
  49. package/cpp/shared/operators/connection/DisconnectOperator.hpp +15 -0
  50. package/cpp/shared/operators/connection/InitializeOperator.cpp +12 -0
  51. package/cpp/shared/operators/connection/InitializeOperator.hpp +22 -0
  52. package/cpp/shared/operators/connection/ListSharesOperator.cpp +13 -0
  53. package/cpp/shared/operators/connection/ListSharesOperator.hpp +18 -0
  54. package/cpp/shared/operators/listing/GetPathInfoOperator.cpp +43 -0
  55. package/cpp/shared/operators/listing/GetPathInfoOperator.hpp +21 -0
  56. package/cpp/shared/operators/listing/GetSecurityDescriptorOperator.cpp +202 -0
  57. package/cpp/shared/operators/listing/GetSecurityDescriptorOperator.hpp +22 -0
  58. package/cpp/shared/operators/listing/ListDirectoryOperator.cpp +20 -0
  59. package/cpp/shared/operators/listing/ListDirectoryOperator.hpp +24 -0
  60. package/cpp/shared/operators/mutate/CopyItemOperator.cpp +19 -0
  61. package/cpp/shared/operators/mutate/CopyItemOperator.hpp +25 -0
  62. package/cpp/shared/operators/mutate/CreateDirectoryOperator.cpp +28 -0
  63. package/cpp/shared/operators/mutate/CreateDirectoryOperator.hpp +20 -0
  64. package/cpp/shared/operators/mutate/DeleteItemOperator.cpp +96 -0
  65. package/cpp/shared/operators/mutate/DeleteItemOperator.hpp +23 -0
  66. package/cpp/shared/operators/mutate/DuplicateItemOperator.cpp +48 -0
  67. package/cpp/shared/operators/mutate/DuplicateItemOperator.hpp +23 -0
  68. package/cpp/shared/operators/mutate/MoveItemOperator.cpp +32 -0
  69. package/cpp/shared/operators/mutate/MoveItemOperator.hpp +21 -0
  70. package/cpp/shared/operators/mutate/RenameItemOperator.cpp +37 -0
  71. package/cpp/shared/operators/mutate/RenameItemOperator.hpp +21 -0
  72. package/cpp/shared/operators/transfer/DownloadFileOperator.cpp +31 -0
  73. package/cpp/shared/operators/transfer/DownloadFileOperator.hpp +21 -0
  74. package/cpp/shared/operators/transfer/UploadFileOperator.cpp +27 -0
  75. package/cpp/shared/operators/transfer/UploadFileOperator.hpp +21 -0
  76. package/cpp/shared/util/SmbErrorMapper.hpp +229 -0
  77. package/cpp/shared/util/SmbLog.hpp +20 -0
  78. package/docs/API.md +105 -0
  79. package/docs/ARCHITECTURE.md +70 -0
  80. package/docs/TASK_MODEL.md +149 -0
  81. package/ios/include/smb2/libsmb2-dcerpc-lsa.h +172 -0
  82. package/ios/include/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  83. package/ios/include/smb2/libsmb2-dcerpc.h +155 -0
  84. package/ios/include/smb2/libsmb2-raw.h +497 -0
  85. package/ios/include/smb2/libsmb2.h +1384 -0
  86. package/ios/include/smb2/smb2-errors.h +549 -0
  87. package/ios/include/smb2/smb2.h +1251 -0
  88. package/ios/libs/device/libsmb2-device.a +0 -0
  89. package/ios/libs/libsmb2.xcframework/Info.plist +48 -0
  90. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc-lsa.h +172 -0
  91. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  92. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc.h +155 -0
  93. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-raw.h +497 -0
  94. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2.h +1384 -0
  95. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/smb2-errors.h +549 -0
  96. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/smb2.h +1251 -0
  97. package/ios/libs/libsmb2.xcframework/ios-arm64/libsmb2.a +0 -0
  98. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc-lsa.h +172 -0
  99. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  100. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc.h +155 -0
  101. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-raw.h +497 -0
  102. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2.h +1384 -0
  103. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/smb2-errors.h +549 -0
  104. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/smb2.h +1251 -0
  105. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/libsmb2.a +0 -0
  106. package/ios/libs/simulator/libsmb2-simulator.a +0 -0
  107. package/lib/ReactNativeSmb.d.ts +200 -0
  108. package/lib/ReactNativeSmb.js +1 -0
  109. package/lib/bridge/decode.d.ts +4 -0
  110. package/lib/bridge/decode.js +92 -0
  111. package/lib/core/SMB.d.ts +3 -0
  112. package/lib/core/SMB.js +4 -0
  113. package/lib/core/SmbClient.d.ts +35 -0
  114. package/lib/core/SmbClient.js +99 -0
  115. package/lib/core/SmbTask.d.ts +41 -0
  116. package/lib/core/SmbTask.js +74 -0
  117. package/lib/core/TransferStore.d.ts +22 -0
  118. package/lib/core/TransferStore.js +88 -0
  119. package/lib/core/ids.d.ts +1 -0
  120. package/lib/core/ids.js +3 -0
  121. package/lib/core/taskResult.d.ts +3 -0
  122. package/lib/core/taskResult.js +52 -0
  123. package/lib/hooks/useSubscribe.d.ts +20 -0
  124. package/lib/hooks/useSubscribe.js +36 -0
  125. package/lib/hooks/useTransfers.d.ts +7 -0
  126. package/lib/hooks/useTransfers.js +29 -0
  127. package/lib/index.d.ts +7 -0
  128. package/lib/index.js +7 -0
  129. package/lib/labels.d.ts +6 -0
  130. package/lib/labels.js +71 -0
  131. package/lib/types.d.ts +141 -0
  132. package/lib/types.js +59 -0
  133. package/lib/utils.d.ts +79 -0
  134. package/lib/utils.js +153 -0
  135. package/package.json +63 -0
  136. package/scripts/build-libsmb2.sh +143 -0
  137. package/scripts/create-xcframework.sh +84 -0
@@ -0,0 +1,45 @@
1
+ // SMB file I/O helpers — sync and async pipelined variants.
2
+ #pragma once
3
+
4
+ #include <atomic>
5
+ #include <cstdint>
6
+ #include <cstddef>
7
+ #include <ctime>
8
+ #include <functional>
9
+ #include <string>
10
+ #include <vector>
11
+
12
+ #include "../ReactNativeSmb.hpp"
13
+ #include "../core/CancellationToken.hpp"
14
+
15
+ namespace react_native_smb {
16
+
17
+ // Sync helpers run on the I/O thread.
18
+
19
+ // Read remote SMB file to local path. Returns total bytes read.
20
+ int64_t smbReadFile(
21
+ void* ctx, const std::string& remotePath, const std::string& localPath, std::function<void(double, double)> progressHandler = [](double, double) {}, const CancellationToken& cancel = {});
22
+
23
+ // Upload local file to remote SMB path. Returns total bytes written.
24
+ int64_t smbWriteFile(
25
+ void* ctx, const std::string& localPath, const std::string& remotePath, std::function<void(double, double)> progressHandler = [](double, double) {}, const CancellationToken& cancel = {});
26
+
27
+ // Copy SMB file to another SMB location. Returns total bytes copied.
28
+ // totalBytesCopied: shared counter for cumulative progress across multiple files.
29
+ int64_t smbCopyFile(void* ctx, const std::string& fromPath, const std::string& toPath, std::shared_ptr<int64_t> totalBytesCopied, int64_t totalSize,
30
+ std::function<void(double, double)> progressHandler = {}, const CancellationToken& cancel = {});
31
+
32
+ // Async pipelined helpers (drive poll loop on caller thread; call under connectionMutex_).
33
+
34
+ // Async pipelined download. Returns total bytes read.
35
+ int64_t smbReadFileAsync(void* ctx, const std::string& remotePath, const std::string& localPath, std::function<void(double, double)> progressHandler = {}, const CancellationToken& cancel = {});
36
+
37
+ // Async pipelined upload. Returns total bytes written.
38
+ int64_t smbWriteFileAsync(void* ctx, const std::string& localPath, const std::string& remotePath, std::function<void(double, double)> progressHandler = {}, const CancellationToken& cancel = {});
39
+
40
+ // Async pipelined SMB->SMB copy on the same context.
41
+ // totalBytesCopied: shared counter for cumulative progress. Returns bytes copied.
42
+ int64_t smbCopyFileAsync(void* ctx, const std::string& fromPath, const std::string& toPath, std::shared_ptr<int64_t> totalBytesCopied, int64_t totalSize,
43
+ std::function<void(double, double)> progressHandler = {}, const CancellationToken& cancel = {});
44
+
45
+ } // namespace react_native_smb
@@ -0,0 +1,75 @@
1
+ #pragma once
2
+
3
+ #include <smb2/libsmb2.h>
4
+ #include <smb2/smb2.h>
5
+
6
+ #include <cstdint>
7
+ #include <string>
8
+
9
+ #include "../ReactNativeSmb.hpp" // SmbFileInfo
10
+
11
+ namespace react_native_smb {
12
+
13
+ // Path and stat helpers shared by operators.
14
+ namespace path_util {
15
+
16
+ // Strip a single leading '/'; map "." / "/" / "" to empty (libsmb2 root form).
17
+ inline std::string normalized(const std::string& path) {
18
+ std::string p = path;
19
+ if (p == "." || p == "/" || p.empty()) {
20
+ p = "";
21
+ } else if (p[0] == '/') {
22
+ p = p.substr(1);
23
+ }
24
+ return p;
25
+ }
26
+
27
+ // Join base + child with exactly one separator.
28
+ inline std::string buildUrl(const std::string& baseUrl, const std::string& path) {
29
+ if (path.empty() || path == "/") return baseUrl;
30
+ if (baseUrl.empty()) return path;
31
+ std::string result = baseUrl;
32
+ if (result.back() != '/' && path.front() != '/') result += "/";
33
+ result += path;
34
+ return result;
35
+ }
36
+
37
+ inline std::string extractFileName(const std::string& path) {
38
+ size_t lastSlash = path.find_last_of("/\\");
39
+ return (lastSlash != std::string::npos) ? path.substr(lastSlash + 1) : path;
40
+ }
41
+
42
+ inline std::string parentOf(const std::string& path) {
43
+ size_t lastSlash = path.find_last_of("/\\");
44
+ std::string parent = (lastSlash != std::string::npos && lastSlash > 0) ? path.substr(0, lastSlash) : "/";
45
+ if (parent.empty()) parent = "/";
46
+ return parent;
47
+ }
48
+
49
+ // Strip a "file://" prefix from a local URI.
50
+ inline std::string convertUriToPath(const std::string& path) {
51
+ const std::string fileProtocol = "file://";
52
+ if (path.find(fileProtocol) == 0) return path.substr(fileProtocol.length());
53
+ return path;
54
+ }
55
+
56
+ // Build an SmbFileInfo from a stat struct (childCount unknown = -1).
57
+ inline SmbFileInfo makeFileInfo(const struct smb2_stat_64& stat, const std::string& name, const std::string& path) {
58
+ bool isDirectory = (stat.smb2_type & SMB2_TYPE_DIRECTORY) != 0;
59
+ int64_t size = isDirectory ? 0 : static_cast<int64_t>(stat.smb2_size);
60
+ return SmbFileInfo{
61
+ name,
62
+ path,
63
+ size,
64
+ isDirectory,
65
+ static_cast<int64_t>(stat.smb2_mtime),
66
+ static_cast<int64_t>(stat.smb2_atime),
67
+ static_cast<int64_t>(stat.smb2_btime),
68
+ static_cast<int64_t>(stat.smb2_ctime),
69
+ -1,
70
+ {},
71
+ };
72
+ }
73
+
74
+ } // namespace path_util
75
+ } // namespace react_native_smb
@@ -0,0 +1,308 @@
1
+ #include "SmbSecurity.hpp"
2
+
3
+ #include <iomanip>
4
+ #include <sstream>
5
+
6
+ namespace react_native_smb {
7
+
8
+ std::string SmbSecurity::convertSidToString(struct smb2_sid* sid) {
9
+ if (!sid) {
10
+ return "";
11
+ }
12
+
13
+ std::stringstream ss;
14
+ ss << "S-1";
15
+
16
+ // Convert identifier authority
17
+ uint64_t ia = 0;
18
+ for (int i = 0; i < SID_ID_AUTH_LEN; i++) {
19
+ ia <<= 8;
20
+ ia |= sid->id_auth[i];
21
+ }
22
+
23
+ if (ia <= 0xffffffff) {
24
+ ss << "-" << ia;
25
+ } else {
26
+ ss << "-0x" << std::hex << ia;
27
+ }
28
+
29
+ // Convert sub-authorities
30
+ for (int i = 0; i < sid->sub_auth_count; i++) {
31
+ ss << "-" << sid->sub_auth[i];
32
+ }
33
+
34
+ return ss.str();
35
+ }
36
+
37
+ std::vector<std::string> SmbSecurity::convertControlFlags(const std::uint16_t& control, bool longForm) {
38
+ std::vector<std::string> flags;
39
+
40
+ if (control == 0) {
41
+ flags.push_back("None");
42
+ return flags;
43
+ }
44
+
45
+ if (control & SMB2_SD_CONTROL_SR) flags.push_back(longForm ? "SELF_RELATIVE" : "SR");
46
+ if (control & SMB2_SD_CONTROL_RM) flags.push_back(longForm ? "RM_CONTROL_VALID" : "RM");
47
+ if (control & SMB2_SD_CONTROL_PS) flags.push_back(longForm ? "SACL_PROTECTED" : "PS");
48
+ if (control & SMB2_SD_CONTROL_PD) flags.push_back(longForm ? "DACL_PROTECTED" : "PD");
49
+ if (control & SMB2_SD_CONTROL_SI) flags.push_back(longForm ? "SACL_AUTO_INHERITED" : "SI");
50
+ if (control & SMB2_SD_CONTROL_DI) flags.push_back(longForm ? "DACL_AUTO_INHERITED" : "DI");
51
+ if (control & SMB2_SD_CONTROL_SC) flags.push_back(longForm ? "SACL_COMPUTED_INHERITANCE_REQUIRED" : "SC");
52
+ if (control & SMB2_SD_CONTROL_DC) flags.push_back(longForm ? "DACL_COMPUTED_INHERITANCE_REQUIRED" : "DC");
53
+ if (control & SMB2_SD_CONTROL_DT) flags.push_back(longForm ? "DACL_TRUSTED" : "DT");
54
+ if (control & SMB2_SD_CONTROL_SS) flags.push_back(longForm ? "SERVER_SECURITY" : "SS");
55
+ if (control & SMB2_SD_CONTROL_SD) flags.push_back(longForm ? "SACL_DEFAULTED" : "SD");
56
+ if (control & SMB2_SD_CONTROL_SP) flags.push_back(longForm ? "SACL_PRESENT" : "SP");
57
+ if (control & SMB2_SD_CONTROL_DD) flags.push_back(longForm ? "DACL_DEFAULTED" : "DD");
58
+ if (control & SMB2_SD_CONTROL_DP) flags.push_back(longForm ? "DACL_PRESENT" : "DP");
59
+ if (control & SMB2_SD_CONTROL_GD) flags.push_back(longForm ? "GROUP_DEFAULTED" : "GD");
60
+ if (control & SMB2_SD_CONTROL_OD) flags.push_back(longForm ? "OWNER_DEFAULTED" : "OD");
61
+
62
+ if (flags.empty()) {
63
+ std::stringstream ss;
64
+ ss << "0x" << std::hex << control;
65
+ flags.push_back(ss.str());
66
+ }
67
+
68
+ return flags;
69
+ }
70
+
71
+ std::vector<std::string> SmbSecurity::convertAccessMask(const uint32_t& mask) {
72
+ std::vector<std::string> permissions;
73
+
74
+ if (mask == 0) {
75
+ permissions.push_back("None");
76
+ return permissions;
77
+ }
78
+
79
+ // Generic access rights (highest priority)
80
+ if (mask & SMB2_GENERIC_ALL) permissions.push_back("GENERIC_ALL");
81
+ if (mask & SMB2_GENERIC_EXECUTE) permissions.push_back("GENERIC_EXECUTE");
82
+ if (mask & SMB2_GENERIC_WRITE) permissions.push_back("GENERIC_WRITE");
83
+ if (mask & SMB2_GENERIC_READ) permissions.push_back("GENERIC_READ");
84
+
85
+ // Standard access rights
86
+ if (mask & SMB2_MAXIMUM_ALLOWED) permissions.push_back("MAXIMUM_ALLOWED");
87
+ if (mask & SMB2_ACCESS_SYSTEM_SECURITY) permissions.push_back("ACCESS_SYSTEM_SECURITY");
88
+ if (mask & SMB2_SYNCHRONIZE) permissions.push_back("SYNCHRONIZE");
89
+ if (mask & SMB2_WRITE_OWNER) permissions.push_back("WRITE_OWNER");
90
+ if (mask & SMB2_WRITE_DACL) permissions.push_back("WRITE_DACL");
91
+ if (mask & SMB2_READ_CONTROL) permissions.push_back("READ_CONTROL");
92
+ if (mask & SMB2_DELETE) permissions.push_back("DELETE");
93
+
94
+ // File/directory specific access rights
95
+ if (mask & SMB2_FILE_WRITE_ATTRIBUTES) permissions.push_back("WRITE_ATTRIBUTES");
96
+ if (mask & SMB2_FILE_READ_ATTRIBUTES) permissions.push_back("READ_ATTRIBUTES");
97
+ if (mask & SMB2_FILE_DELETE_CHILD) permissions.push_back("DELETE_CHILD");
98
+ if (mask & SMB2_FILE_EXECUTE) permissions.push_back("EXECUTE");
99
+ if (mask & SMB2_FILE_WRITE_EA) permissions.push_back("WRITE_EA");
100
+ if (mask & SMB2_FILE_READ_EA) permissions.push_back("READ_EA");
101
+
102
+ // File specific rights
103
+ if (mask & SMB2_FILE_APPEND_DATA) permissions.push_back("APPEND_DATA");
104
+ if (mask & SMB2_FILE_WRITE_DATA) permissions.push_back("WRITE_DATA");
105
+ if (mask & SMB2_FILE_READ_DATA) permissions.push_back("READ_DATA");
106
+
107
+ if (permissions.empty()) {
108
+ std::stringstream ss;
109
+ ss << "0x" << std::hex << mask;
110
+ permissions.push_back(ss.str());
111
+ }
112
+
113
+ return permissions;
114
+ }
115
+
116
+ std::vector<std::string> SmbSecurity::convertAccessMask(const uint32_t& mask, bool isDirectory) {
117
+ std::vector<std::string> permissions;
118
+
119
+ if (mask == 0) {
120
+ permissions.push_back("None");
121
+ return permissions;
122
+ }
123
+
124
+ // Generic access rights (highest priority)
125
+ if (mask & SMB2_GENERIC_ALL) permissions.push_back("GENERIC_ALL");
126
+ if (mask & SMB2_GENERIC_EXECUTE) permissions.push_back("GENERIC_EXECUTE");
127
+ if (mask & SMB2_GENERIC_WRITE) permissions.push_back("GENERIC_WRITE");
128
+ if (mask & SMB2_GENERIC_READ) permissions.push_back("GENERIC_READ");
129
+
130
+ // Standard access rights
131
+ if (mask & SMB2_MAXIMUM_ALLOWED) permissions.push_back("MAXIMUM_ALLOWED");
132
+ if (mask & SMB2_ACCESS_SYSTEM_SECURITY) permissions.push_back("ACCESS_SYSTEM_SECURITY");
133
+ if (mask & SMB2_SYNCHRONIZE) permissions.push_back("SYNCHRONIZE");
134
+ if (mask & SMB2_WRITE_OWNER) permissions.push_back("WRITE_OWNER");
135
+ if (mask & SMB2_WRITE_DACL) permissions.push_back("WRITE_DACL");
136
+ if (mask & SMB2_READ_CONTROL) permissions.push_back("READ_CONTROL");
137
+ if (mask & SMB2_DELETE) permissions.push_back("DELETE");
138
+
139
+ // File/directory specific access rights
140
+ if (mask & SMB2_FILE_WRITE_ATTRIBUTES) permissions.push_back("WRITE_ATTRIBUTES");
141
+ if (mask & SMB2_FILE_READ_ATTRIBUTES) permissions.push_back("READ_ATTRIBUTES");
142
+ if (mask & SMB2_FILE_DELETE_CHILD) permissions.push_back("DELETE_CHILD");
143
+ if (mask & SMB2_FILE_WRITE_EA) permissions.push_back("WRITE_EA");
144
+ if (mask & SMB2_FILE_READ_EA) permissions.push_back("READ_EA");
145
+
146
+ // Context-specific rights
147
+ if (isDirectory) {
148
+ if (mask & SMB2_FILE_LIST_DIRECTORY) permissions.push_back("LIST_DIRECTORY");
149
+ if (mask & SMB2_FILE_ADD_FILE) permissions.push_back("ADD_FILE");
150
+ if (mask & SMB2_FILE_ADD_SUBDIRECTORY) permissions.push_back("ADD_SUBDIRECTORY");
151
+ if (mask & SMB2_FILE_TRAVERSE) permissions.push_back("TRAVERSE");
152
+ } else {
153
+ if (mask & SMB2_FILE_READ_DATA) permissions.push_back("READ_DATA");
154
+ if (mask & SMB2_FILE_WRITE_DATA) permissions.push_back("WRITE_DATA");
155
+ if (mask & SMB2_FILE_APPEND_DATA) permissions.push_back("APPEND_DATA");
156
+ if (mask & SMB2_FILE_EXECUTE) permissions.push_back("EXECUTE");
157
+ }
158
+
159
+ if (permissions.empty()) {
160
+ std::stringstream ss;
161
+ ss << "0x" << std::hex << mask;
162
+ permissions.push_back(ss.str());
163
+ }
164
+
165
+ return permissions;
166
+ }
167
+
168
+ std::string SmbSecurity::convertAceType(const uint8_t& aceType) {
169
+ switch (aceType) {
170
+ case SMB2_ACCESS_ALLOWED_ACE_TYPE:
171
+ return "ACCESS_ALLOWED";
172
+ case SMB2_ACCESS_DENIED_ACE_TYPE:
173
+ return "ACCESS_DENIED";
174
+ case SMB2_SYSTEM_AUDIT_ACE_TYPE:
175
+ return "SYSTEM_AUDIT";
176
+ case SMB2_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
177
+ return "ACCESS_ALLOWED_OBJECT";
178
+ case SMB2_ACCESS_DENIED_OBJECT_ACE_TYPE:
179
+ return "ACCESS_DENIED_OBJECT";
180
+ case SMB2_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
181
+ return "SYSTEM_AUDIT_OBJECT";
182
+ case SMB2_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
183
+ return "ACCESS_ALLOWED_CALLBACK";
184
+ case SMB2_ACCESS_DENIED_CALLBACK_ACE_TYPE:
185
+ return "ACCESS_DENIED_CALLBACK";
186
+ case SMB2_SYSTEM_MANDATORY_LABEL_ACE_TYPE:
187
+ return "SYSTEM_MANDATORY_LABEL";
188
+ case SMB2_SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE:
189
+ return "SYSTEM_RESOURCE_ATTRIBUTE";
190
+ case SMB2_SYSTEM_SCOPED_POLICY_ID_ACE_TYPE:
191
+ return "SYSTEM_SCOPED_POLICY_ID";
192
+ default:
193
+ std::stringstream ss;
194
+ ss << "UNKNOWN_TYPE_0x" << std::hex << static_cast<int>(aceType);
195
+ return ss.str();
196
+ }
197
+ }
198
+
199
+ std::vector<std::string> SmbSecurity::convertAceFlags(const uint8_t& aceFlags) {
200
+ std::vector<std::string> flags;
201
+
202
+ if (aceFlags == 0) {
203
+ flags.push_back("None");
204
+ return flags;
205
+ }
206
+
207
+ if (aceFlags & SMB2_OBJECT_INHERIT_ACE) flags.push_back("OBJECT_INHERIT");
208
+ if (aceFlags & SMB2_CONTAINER_INHERIT_ACE) flags.push_back("CONTAINER_INHERIT");
209
+ if (aceFlags & SMB2_NO_PROPAGATE_INHERIT_ACE) flags.push_back("NO_PROPAGATE_INHERIT");
210
+ if (aceFlags & SMB2_INHERIT_ONLY_ACE) flags.push_back("INHERIT_ONLY");
211
+ if (aceFlags & SMB2_INHERITED_ACE) flags.push_back("INHERITED");
212
+ if (aceFlags & SMB2_SUCCESSFUL_ACCESS_ACE_FLAG) flags.push_back("SUCCESSFUL_ACCESS");
213
+ if (aceFlags & SMB2_FAILED_ACCESS_ACE_FLAG) flags.push_back("FAILED_ACCESS");
214
+
215
+ if (flags.empty()) {
216
+ std::stringstream ss;
217
+ ss << "0x" << std::hex << static_cast<int>(aceFlags);
218
+ flags.push_back(ss.str());
219
+ }
220
+
221
+ return flags;
222
+ }
223
+
224
+ SmbAcl SmbSecurity::convertAclToSmbAcl(struct smb2_acl* acl) {
225
+ SmbAcl result;
226
+ if (!acl) {
227
+ return result;
228
+ }
229
+
230
+ result.revision = acl->revision;
231
+ result.aceCount = acl->ace_count;
232
+
233
+ struct smb2_ace* ace = acl->aces;
234
+ int aceIndex = 0;
235
+
236
+ while (ace && aceIndex < acl->ace_count) {
237
+ try {
238
+ result.aces.push_back(convertAceToSmbAce(ace));
239
+ ace = ace->next;
240
+ aceIndex++;
241
+ } catch (const std::exception& e) {
242
+ break;
243
+ }
244
+ }
245
+
246
+ result.aceCount = static_cast<uint16_t>(result.aces.size());
247
+
248
+ return result;
249
+ }
250
+
251
+ SmbAce SmbSecurity::convertAceToSmbAce(struct smb2_ace* ace) {
252
+ SmbAce result;
253
+ if (!ace) {
254
+ return result;
255
+ }
256
+
257
+ result.aceType = convertAceType(ace->ace_type);
258
+ result.aceFlags = convertAceFlags(ace->ace_flags);
259
+ result.mask = convertAccessMask(ace->mask);
260
+ result.sid = SmbSecurity::convertSidToString(ace->sid);
261
+
262
+ return result;
263
+ }
264
+
265
+ SmbSecurityDescriptor SmbSecurity::processSecurityDescriptor(struct smb2_security_descriptor* sd) {
266
+ SmbSecurityDescriptor result{0, {}, "", "", SmbAcl{0, 0, {}}};
267
+
268
+ if (!sd) {
269
+ return result;
270
+ }
271
+
272
+ // Set revision
273
+ result.revision = sd->revision;
274
+
275
+ if (sd->control) {
276
+ result.control = convertControlFlags(sd->control, true);
277
+ } else {
278
+ result.control = {"None"};
279
+ }
280
+
281
+ // Convert Owner, Group, and DACL
282
+ if (sd->owner) {
283
+ result.ownerSid = convertSidToString(sd->owner);
284
+ } else {
285
+ result.ownerSid = "";
286
+ }
287
+
288
+ if (sd->group) {
289
+ result.groupSid = convertSidToString(sd->group);
290
+ } else {
291
+ result.groupSid = "";
292
+ }
293
+
294
+ if (sd->dacl) {
295
+ result.dacl = convertAclToSmbAcl(sd->dacl);
296
+ } else {
297
+ result.dacl = SmbAcl{0, 0, {}};
298
+ }
299
+
300
+ return result;
301
+ }
302
+
303
+ void SmbSecurity::freeAcl(struct smb2_acl* acl) {
304
+ if (acl) {
305
+ free(acl);
306
+ }
307
+ }
308
+ } // namespace react_native_smb
@@ -0,0 +1,32 @@
1
+ #pragma once
2
+
3
+ #include "../ReactNativeSmb.hpp"
4
+ #include <cstdint>
5
+ #include <cstddef>
6
+ #include <ctime>
7
+ #include <smb2/smb2.h>
8
+ #include <smb2/libsmb2.h>
9
+ #include <string>
10
+
11
+ namespace react_native_smb {
12
+ class SmbSecurity {
13
+ public:
14
+ static std::string convertSidToString(struct smb2_sid* sid);
15
+
16
+ static std::vector<std::string> convertControlFlags(const std::uint16_t& control, bool longForm = true);
17
+
18
+ static std::vector<std::string> convertAccessMask(const uint32_t& mask);
19
+ static std::vector<std::string> convertAccessMask(const uint32_t& mask, bool isDirectory);
20
+
21
+ static std::string convertAceType(const uint8_t& aceType);
22
+ static std::vector<std::string> convertAceFlags(const uint8_t& aceFlags);
23
+
24
+ static SmbAcl convertAclToSmbAcl(struct smb2_acl* acl);
25
+ static SmbAce convertAceToSmbAce(struct smb2_ace* ace);
26
+
27
+ static SmbSecurityDescriptor processSecurityDescriptor(struct smb2_security_descriptor* sd);
28
+
29
+ private:
30
+ static void freeAcl(struct smb2_acl* acl);
31
+ };
32
+ } // namespace react_native_smb
@@ -0,0 +1,112 @@
1
+ #pragma once
2
+
3
+ #include <smb2/libsmb2.h>
4
+ #include <smb2/smb2.h>
5
+
6
+ #include <cctype>
7
+ #include <sstream>
8
+ #include <string>
9
+ #include <vector>
10
+
11
+ #include "../ReactNativeSmb.hpp" // SmbFileInfo
12
+ #include "../core/CancellationToken.hpp"
13
+ #include "SmbDirScan.hpp"
14
+ #include "SmbPathUtil.hpp"
15
+
16
+ namespace react_native_smb {
17
+
18
+ // Tree helpers for delete, copy, and duplicate operators.
19
+ namespace tree_ops {
20
+
21
+ // Depth-first collect of every descendant (children appended before parent so
22
+ // callers can rmdir deepest-first). Skips inaccessible sub-dirs.
23
+ inline void collectAllItems(smb2_context* ctx, const std::string& path, std::vector<SmbFileInfo>& allItems, const CancellationToken& cancel) {
24
+ try {
25
+ std::vector<SmbFileInfo> contents = listOnCtx(ctx, path, false, 0, cancel);
26
+ for (const auto& item : contents) {
27
+ if (item.isDirectory) collectAllItems(ctx, item.path, allItems, cancel);
28
+ allItems.push_back(item);
29
+ }
30
+ } catch (const std::exception&) {
31
+ // Permission errors on sub-dirs: skip; parent rmdir reports "not empty".
32
+ }
33
+ }
34
+
35
+ // Recursively total the byte size of a path. Returns partial size on errors.
36
+ inline int64_t calculateTotalSize(smb2_context* ctx, const std::string& path, bool recursive, const CancellationToken& cancel) {
37
+ const std::string norm = path_util::normalized(path);
38
+ struct smb2_stat_64 stat;
39
+ if (smb2_stat(ctx, norm.c_str(), &stat) < 0) return 0;
40
+
41
+ const bool isDirectory = (stat.smb2_type & SMB2_TYPE_DIRECTORY) != 0;
42
+ if (!isDirectory) return static_cast<int64_t>(stat.smb2_size);
43
+ if (!recursive) return 0;
44
+
45
+ int64_t total = 0;
46
+ try {
47
+ std::vector<SmbFileInfo> contents = listOnCtx(ctx, path, false, 0, cancel);
48
+ for (const auto& item : contents) {
49
+ if (item.isDirectory)
50
+ total += calculateTotalSize(ctx, item.path, true, cancel);
51
+ else
52
+ total += item.size;
53
+ }
54
+ } catch (const std::exception&) {
55
+ // Ignore inaccessible directories; return partial size.
56
+ }
57
+ return total;
58
+ }
59
+
60
+ // Generate a unique "<base> copy[ N]<ext>" name not present in parentPath.
61
+ inline std::string generateUniqueCopyName(smb2_context* ctx, const std::string& parentPath, const std::string& originalName, const CancellationToken& cancel) {
62
+ size_t lastDot = originalName.find_last_of('.');
63
+ std::string baseName = (lastDot != std::string::npos && lastDot > 0) ? originalName.substr(0, lastDot) : originalName;
64
+ std::string extension = (lastDot != std::string::npos && lastDot > 0) ? originalName.substr(lastDot) : "";
65
+
66
+ // Strip a previous " copy" / " copy N" suffix so copies-of-copies stay tidy.
67
+ const std::string copySuffix = " copy";
68
+ size_t copyPos = baseName.rfind(copySuffix);
69
+ if (copyPos != std::string::npos) {
70
+ std::string remainder = baseName.substr(copyPos + copySuffix.length());
71
+ bool isClean = false;
72
+ if (remainder.empty()) {
73
+ isClean = true;
74
+ } else if (remainder[0] == ' ') {
75
+ isClean = true;
76
+ for (size_t i = 1; i < remainder.length(); i++) {
77
+ if (!std::isdigit(static_cast<unsigned char>(remainder[i]))) {
78
+ isClean = false;
79
+ break;
80
+ }
81
+ }
82
+ }
83
+ if (isClean) baseName = baseName.substr(0, copyPos);
84
+ }
85
+
86
+ std::vector<SmbFileInfo> existingFiles = listOnCtx(ctx, parentPath, false, 0, cancel);
87
+ std::vector<std::string> existingNames;
88
+ existingNames.reserve(existingFiles.size());
89
+ for (const auto& item : existingFiles) existingNames.push_back(item.name);
90
+
91
+ int counter = 1;
92
+ while (true) {
93
+ std::stringstream ss;
94
+ ss << baseName << " copy";
95
+ if (counter > 1) ss << " " << counter;
96
+ ss << extension;
97
+ std::string candidate = ss.str();
98
+
99
+ bool found = false;
100
+ for (const auto& existing : existingNames) {
101
+ if (existing == candidate) {
102
+ found = true;
103
+ break;
104
+ }
105
+ }
106
+ if (!found) return candidate;
107
+ if (++counter > 10000) return candidate; // safety break
108
+ }
109
+ }
110
+
111
+ } // namespace tree_ops
112
+ } // namespace react_native_smb
@@ -0,0 +1,35 @@
1
+ #pragma once
2
+
3
+ #include "OperatorBase.hpp"
4
+
5
+ // For JSIConverter<T> in publishThisResult convenience.
6
+ #include "../ReactNativeSmb.hpp" // brings the JSIConverter specializations in margelo::nitro namespace
7
+
8
+ namespace jsi = facebook::jsi;
9
+
10
+ namespace react_native_smb {
11
+
12
+ // Operators that produce a value store it here; the concrete HybridSMB method
13
+ // reads it back via result() once the task completes (typed, no erasure).
14
+ // void-producing operators derive from OperatorBase directly.
15
+ template <typename T>
16
+ class Operator : public OperatorBase {
17
+ public:
18
+ const T& result() const { return result_; }
19
+
20
+ protected:
21
+ T result_{};
22
+
23
+ // Convenience for value-producing operators: publish our result_ + the
24
+ // correct converter directly to the owning task. Call this at the end of a
25
+ // successful run() (before or after emitStatus(Success)).
26
+ void publishThisResult() {
27
+ publishResult(std::any(result_), [](jsi::Runtime& rt, const std::any& a) -> jsi::Value {
28
+ const T* v = std::any_cast<T>(&a);
29
+ if (!v) return jsi::Value::undefined();
30
+ return margelo::nitro::JSIConverter<T>::toJSI(rt, *v);
31
+ });
32
+ }
33
+ };
34
+
35
+ } // namespace react_native_smb
@@ -0,0 +1,57 @@
1
+ #include "OperatorBase.hpp"
2
+
3
+ #include "../connection/SmbConnectionPool.hpp"
4
+ #include "../core/SmbTask.hpp"
5
+
6
+ namespace react_native_smb {
7
+
8
+ void OperatorBase::start(SmbTask* task, SmbConnectionPool* pool, const CancellationToken& cancel, size_t opIndex) {
9
+ setContext(OperatorContext{task, pool, cancel, opIndex});
10
+ if (cancel.cancelled()) return;
11
+ run();
12
+ }
13
+
14
+ std::string OperatorBase::owningTaskId() const { return ctx_.task ? ctx_.task->getId() : std::string(); }
15
+
16
+ MetadataContextLease OperatorBase::makeMetadataLease() {
17
+ if (ctx_.task) ctx_.task->markPending();
18
+ MetadataContextLease lease(pool(), kind(), owningTaskId());
19
+ if (ctx_.task && !isCancelled()) ctx_.task->markRunning();
20
+ return lease;
21
+ }
22
+
23
+ PoolContextHandle OperatorBase::requestContext(AcquireMode mode) {
24
+ if (ctx_.task) ctx_.task->markPending();
25
+ PoolContextHandle handle = pool().requestContext(mode, kind(), owningTaskId());
26
+ if (ctx_.task && !isCancelled()) ctx_.task->markRunning();
27
+ return handle;
28
+ }
29
+
30
+ void OperatorBase::emitStatus(SmbTaskStatus s, const std::string& error, int code) {
31
+ if (!ctx_.task) return;
32
+ if (isCancelled() && s == SmbTaskStatus::Success) return;
33
+ if (ctx_.task->getStatus() == SmbTaskStatus::Cancelled && s == SmbTaskStatus::Success) return;
34
+ ctx_.task->onOpStatus(ctx_.opIndex, s, error, code);
35
+ }
36
+
37
+ void OperatorBase::emitProgress(double done, double total) {
38
+ if (ctx_.task) ctx_.task->onOpProgress(ctx_.opIndex, done, total);
39
+ }
40
+
41
+ size_t OperatorBase::spawn(std::vector<std::unique_ptr<OperatorBase>> moreOps) {
42
+ return ctx_.task ? ctx_.task->spawn(std::move(moreOps)) : 0;
43
+ }
44
+
45
+ void OperatorBase::addExpectedBytes(int64_t bytes) {
46
+ if (ctx_.task) ctx_.task->addExpectedBytes(bytes);
47
+ }
48
+
49
+ void OperatorBase::setSourceDestination(const std::string& source, const std::string& destination) {
50
+ if (ctx_.task) ctx_.task->setPaths(source, destination);
51
+ }
52
+
53
+ void OperatorBase::publishResult(std::any value, std::function<jsi::Value(jsi::Runtime&, const std::any&)> converter) {
54
+ if (ctx_.task) ctx_.task->publishResult(std::move(value), std::move(converter));
55
+ }
56
+
57
+ } // namespace react_native_smb