@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,96 @@
1
+ #include "DeleteItemOperator.hpp"
2
+
3
+ #include <smb2/libsmb2.h>
4
+ #include <smb2/smb2.h>
5
+
6
+ #include <algorithm>
7
+ #include <stdexcept>
8
+ #include <vector>
9
+
10
+ #include "../../ReactNativeSmb.hpp"
11
+ #include "../../io/SmbPathUtil.hpp"
12
+ #include "../../io/SmbTreeOps.hpp"
13
+
14
+ namespace react_native_smb {
15
+
16
+ void DeleteItemOperator::run() {
17
+ const CancellationToken token = cancelToken();
18
+ const std::string norm = path_util::normalized(path_);
19
+ setSourceDestination(norm, "");
20
+
21
+ bool isDirectory = false;
22
+ {
23
+ auto handle = requestContext(AcquireMode::Metadata);
24
+ handle.submitSync([&](smb2_context* ctx) {
25
+ struct smb2_stat_64 st;
26
+ if (smb2_stat(ctx, norm.c_str(), &st) < 0) {
27
+ throw std::runtime_error("Delete Failed: Could not stat '" + path_ + "'. Error: " + smb2_get_error(ctx));
28
+ }
29
+ isDirectory = (st.smb2_type & SMB2_TYPE_DIRECTORY) != 0;
30
+ });
31
+ }
32
+
33
+ if (!isDirectory) {
34
+ auto handle = requestContext(AcquireMode::Metadata);
35
+ handle.submitSync([&](smb2_context* ctx) {
36
+ const int r = smb2_unlink(ctx, norm.c_str());
37
+ if (r < 0) throw std::runtime_error("Failed to delete file '" + path_ + "': " + smb2_get_error(ctx));
38
+ });
39
+ emitStatus(SmbTaskStatus::Success);
40
+ return;
41
+ }
42
+
43
+ std::vector<SmbFileInfo> allItems;
44
+ {
45
+ auto handle = requestContext(AcquireMode::Metadata);
46
+ handle.submitSync([&](smb2_context* ctx) { tree_ops::collectAllItems(ctx, path_, allItems, token); });
47
+ }
48
+ if (isCancelled()) {
49
+ emitStatus(SmbTaskStatus::Cancelled);
50
+ return;
51
+ }
52
+
53
+ std::vector<SmbFileInfo> fileItems;
54
+ std::vector<SmbFileInfo> dirItems;
55
+ for (auto& item : allItems) {
56
+ if (item.isDirectory)
57
+ dirItems.push_back(std::move(item));
58
+ else
59
+ fileItems.push_back(std::move(item));
60
+ }
61
+
62
+ if (!fileItems.empty() && !isCancelled()) {
63
+ auto handle = requestContext(AcquireMode::Metadata);
64
+ handle.submitSync([&](smb2_context* ctx) {
65
+ for (const auto& item : fileItems) {
66
+ if (isCancelled()) return;
67
+ std::string n = path_util::normalized(item.path);
68
+ const int r = smb2_unlink(ctx, n.c_str());
69
+ if (r < 0) throw std::runtime_error("Recursive Delete Failed: Could not delete file '" + item.path + "'. Error: " + smb2_get_error(ctx));
70
+ }
71
+ });
72
+ }
73
+ if (isCancelled()) {
74
+ emitStatus(SmbTaskStatus::Cancelled);
75
+ return;
76
+ }
77
+
78
+ std::sort(dirItems.begin(), dirItems.end(), [](const SmbFileInfo& a, const SmbFileInfo& b) { return a.path.length() > b.path.length(); });
79
+ {
80
+ auto handle = requestContext(AcquireMode::Metadata);
81
+ handle.submitSync([&](smb2_context* ctx) {
82
+ for (const auto& item : dirItems) {
83
+ if (isCancelled()) return;
84
+ std::string n = path_util::normalized(item.path);
85
+ const int r = smb2_rmdir(ctx, n.c_str());
86
+ if (r < 0) throw std::runtime_error("Recursive Delete Failed: Could not delete sub-directory '" + item.path + "'. Error: " + smb2_get_error(ctx));
87
+ }
88
+ const int rootR = smb2_rmdir(ctx, norm.c_str());
89
+ if (rootR < 0) throw std::runtime_error("Delete Failed: Could not delete directory '" + path_ + "'. Error: " + smb2_get_error(ctx));
90
+ });
91
+ }
92
+
93
+ emitStatus(SmbTaskStatus::Success);
94
+ }
95
+
96
+ } // namespace react_native_smb
@@ -0,0 +1,23 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include "../OperatorBase.hpp"
6
+
7
+ namespace react_native_smb {
8
+
9
+ // Deletes a file or a directory tree. Directory deletion walks the tree and
10
+ // removes deepest-first (strict ordering), so it runs self-contained on Bulk
11
+ // Metadata slots rather than spawning child operators.
12
+ class DeleteItemOperator : public OperatorBase {
13
+ public:
14
+ explicit DeleteItemOperator(std::string path) : path_(std::move(path)) {}
15
+
16
+ SmbOperatorKind kind() const override { return SmbOperatorKind::DeleteItem; }
17
+ void run() override;
18
+
19
+ private:
20
+ std::string path_;
21
+ };
22
+
23
+ } // namespace react_native_smb
@@ -0,0 +1,48 @@
1
+ #include "DuplicateItemOperator.hpp"
2
+
3
+ #include <smb2/libsmb2.h>
4
+ #include <smb2/smb2.h>
5
+
6
+ #include <string>
7
+
8
+ #include "../../io/SmbCopyTree.hpp"
9
+ #include "../../io/SmbPathUtil.hpp"
10
+ #include "../../io/SmbTreeOps.hpp"
11
+
12
+ namespace react_native_smb {
13
+
14
+ void DuplicateItemOperator::run() {
15
+ const CancellationToken token = cancelToken();
16
+
17
+ const std::string parentPath = path_util::parentOf(path_);
18
+ const std::string fileName = path_util::extractFileName(path_);
19
+
20
+ MetadataContextLease lease = makeMetadataLease();
21
+
22
+ std::string destPath;
23
+ lease.submitSync([&](smb2_context* ctx) {
24
+ std::string newName = tree_ops::generateUniqueCopyName(ctx, parentPath, fileName, token);
25
+ destPath = path_util::buildUrl(parentPath, newName);
26
+ });
27
+
28
+ if (isCancelled() || destPath.empty()) {
29
+ emitStatus(SmbTaskStatus::Cancelled);
30
+ return;
31
+ }
32
+
33
+ setSourceDestination(path_, destPath);
34
+
35
+ copyTreeImpl(pool(), kind(), path_, destPath, /*recursive=*/true, token, [this](double done, double total) { emitProgress(done, total); },
36
+ [this](int64_t n) { addExpectedBytes(n); }, owningTaskId(), &lease);
37
+
38
+ if (isCancelled()) {
39
+ emitStatus(SmbTaskStatus::Cancelled);
40
+ return;
41
+ }
42
+
43
+ result_ = destPath;
44
+ publishThisResult();
45
+ emitStatus(SmbTaskStatus::Success);
46
+ }
47
+
48
+ } // namespace react_native_smb
@@ -0,0 +1,23 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include "../Operator.hpp"
6
+
7
+ namespace react_native_smb {
8
+
9
+ // Duplicates a file or directory into the same parent with a unique
10
+ // "<name> copy" suffix. Returns the new path. Self-contained (reuses the same
11
+ // tree-copy logic as CopyItemOperator).
12
+ class DuplicateItemOperator : public Operator<std::string> {
13
+ public:
14
+ explicit DuplicateItemOperator(std::string path) : path_(std::move(path)) {}
15
+
16
+ SmbOperatorKind kind() const override { return SmbOperatorKind::DuplicateItem; }
17
+ void run() override;
18
+
19
+ private:
20
+ std::string path_;
21
+ };
22
+
23
+ } // namespace react_native_smb
@@ -0,0 +1,32 @@
1
+ #include "MoveItemOperator.hpp"
2
+
3
+ #include <smb2/libsmb2.h>
4
+ #include <smb2/smb2.h>
5
+
6
+ #include <stdexcept>
7
+
8
+ #include "../../connection/SmbConnectionPool.hpp"
9
+ #include "../../io/SmbPathUtil.hpp"
10
+
11
+ namespace react_native_smb {
12
+
13
+ void MoveItemOperator::run() {
14
+
15
+ const std::string from = path_util::normalized(fromPath_);
16
+ const std::string to = path_util::normalized(toPath_);
17
+
18
+ setSourceDestination(from, to);
19
+
20
+ auto handle = requestContext(AcquireMode::Interactive);
21
+
22
+ handle.submitSync([&](smb2_context* ctx) {
23
+ const int r = smb2_rename(ctx, from.c_str(), to.c_str());
24
+ if (r < 0) {
25
+ throw std::runtime_error("Move Failed: Could not move '" + fromPath_ + "' to '" + toPath_ + "'. Error: " + smb2_get_error(ctx));
26
+ }
27
+ });
28
+
29
+ emitStatus(SmbTaskStatus::Success);
30
+ }
31
+
32
+ } // namespace react_native_smb
@@ -0,0 +1,21 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include "../OperatorBase.hpp"
6
+
7
+ namespace react_native_smb {
8
+
9
+ class MoveItemOperator : public OperatorBase {
10
+ public:
11
+ MoveItemOperator(std::string fromPath, std::string toPath) : fromPath_(std::move(fromPath)), toPath_(std::move(toPath)) {}
12
+
13
+ SmbOperatorKind kind() const override { return SmbOperatorKind::MoveItem; }
14
+ void run() override;
15
+
16
+ private:
17
+ std::string fromPath_;
18
+ std::string toPath_;
19
+ };
20
+
21
+ } // namespace react_native_smb
@@ -0,0 +1,37 @@
1
+ #include "RenameItemOperator.hpp"
2
+
3
+ #include <smb2/libsmb2.h>
4
+ #include <smb2/smb2.h>
5
+
6
+ #include <stdexcept>
7
+
8
+ #include "../../connection/SmbConnectionPool.hpp"
9
+ #include "../../io/SmbPathUtil.hpp"
10
+
11
+ namespace react_native_smb {
12
+
13
+ void RenameItemOperator::run() {
14
+ if (newName_.empty() || newName_.find('/') != std::string::npos || newName_.find('\\') != std::string::npos) {
15
+ throw std::runtime_error("Rename Failed: invalid new name '" + newName_ + "'");
16
+ }
17
+
18
+
19
+ const std::string normCurrent = path_util::normalized(currentPath_);
20
+ const std::string parentDir = path_util::parentOf(currentPath_);
21
+ const std::string newPath = path_util::normalized(path_util::buildUrl(parentDir, newName_));
22
+
23
+ setSourceDestination(normCurrent, newPath);
24
+
25
+ auto handle = requestContext(AcquireMode::Interactive);
26
+
27
+ handle.submitSync([&](smb2_context* ctx) {
28
+ const int r = smb2_rename(ctx, normCurrent.c_str(), newPath.c_str());
29
+ if (r < 0) {
30
+ throw std::runtime_error("Rename Failed: Could not rename '" + currentPath_ + "' to '" + newName_ + "'. Error: " + smb2_get_error(ctx));
31
+ }
32
+ });
33
+
34
+ emitStatus(SmbTaskStatus::Success);
35
+ }
36
+
37
+ } // namespace react_native_smb
@@ -0,0 +1,21 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include "../OperatorBase.hpp"
6
+
7
+ namespace react_native_smb {
8
+
9
+ class RenameItemOperator : public OperatorBase {
10
+ public:
11
+ RenameItemOperator(std::string currentPath, std::string newName) : currentPath_(std::move(currentPath)), newName_(std::move(newName)) {}
12
+
13
+ SmbOperatorKind kind() const override { return SmbOperatorKind::RenameItem; }
14
+ void run() override;
15
+
16
+ private:
17
+ std::string currentPath_;
18
+ std::string newName_;
19
+ };
20
+
21
+ } // namespace react_native_smb
@@ -0,0 +1,31 @@
1
+ #include "DownloadFileOperator.hpp"
2
+
3
+ #include "../../connection/SmbConnectionPool.hpp"
4
+ #include "../../io/SmbFileIO.hpp"
5
+ #include "../../io/SmbPathUtil.hpp"
6
+
7
+ namespace react_native_smb {
8
+
9
+ void DownloadFileOperator::run() {
10
+
11
+ const std::string remote = path_util::normalized(remotePath_);
12
+ const std::string local = path_util::convertUriToPath(localPath_);
13
+
14
+ setSourceDestination(remote, local);
15
+
16
+ auto handle = requestContext(AcquireMode::Metadata);
17
+
18
+ const CancellationToken token = cancelToken();
19
+ handle.submitSync([&](smb2_context* ctx) {
20
+ smbReadFileAsync(
21
+ ctx, remote, local, [this](double done, double total) { emitProgress(done, total); }, token);
22
+ });
23
+
24
+ if (isCancelled()) {
25
+ emitStatus(SmbTaskStatus::Cancelled);
26
+ return;
27
+ }
28
+ emitStatus(SmbTaskStatus::Success);
29
+ }
30
+
31
+ } // namespace react_native_smb
@@ -0,0 +1,21 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include "../OperatorBase.hpp"
6
+
7
+ namespace react_native_smb {
8
+
9
+ class DownloadFileOperator : public OperatorBase {
10
+ public:
11
+ DownloadFileOperator(std::string remotePath, std::string localPath) : remotePath_(std::move(remotePath)), localPath_(std::move(localPath)) {}
12
+
13
+ SmbOperatorKind kind() const override { return SmbOperatorKind::DownloadFile; }
14
+ void run() override;
15
+
16
+ private:
17
+ std::string remotePath_;
18
+ std::string localPath_;
19
+ };
20
+
21
+ } // namespace react_native_smb
@@ -0,0 +1,27 @@
1
+ #include "UploadFileOperator.hpp"
2
+
3
+ #include "../../connection/SmbConnectionPool.hpp"
4
+ #include "../../io/SmbFileIO.hpp"
5
+ #include "../../io/SmbPathUtil.hpp"
6
+
7
+ namespace react_native_smb {
8
+
9
+ void UploadFileOperator::run() {
10
+
11
+ const std::string remote = path_util::normalized(remotePath_);
12
+ const std::string local = path_util::convertUriToPath(localPath_);
13
+
14
+ setSourceDestination(local, remote); // local -> remote for upload
15
+
16
+ auto handle = requestContext(AcquireMode::Metadata);
17
+
18
+ const CancellationToken token = cancelToken();
19
+ handle.submitSync([&](smb2_context* ctx) {
20
+ smbWriteFileAsync(
21
+ ctx, local, remote, [this](double done, double total) { emitProgress(done, total); }, token);
22
+ });
23
+
24
+ emitStatus(SmbTaskStatus::Success);
25
+ }
26
+
27
+ } // namespace react_native_smb
@@ -0,0 +1,21 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include "../OperatorBase.hpp"
6
+
7
+ namespace react_native_smb {
8
+
9
+ class UploadFileOperator : public OperatorBase {
10
+ public:
11
+ UploadFileOperator(std::string localPath, std::string remotePath) : localPath_(std::move(localPath)), remotePath_(std::move(remotePath)) {}
12
+
13
+ SmbOperatorKind kind() const override { return SmbOperatorKind::UploadFile; }
14
+ void run() override;
15
+
16
+ private:
17
+ std::string localPath_;
18
+ std::string remotePath_;
19
+ };
20
+
21
+ } // namespace react_native_smb
@@ -0,0 +1,229 @@
1
+ #pragma once
2
+
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <cerrno>
6
+ #include <cstdint>
7
+ #include <initializer_list>
8
+ #include <optional>
9
+ #include <string>
10
+
11
+ namespace react_native_smb {
12
+
13
+ enum class SmbErrorCode : int {
14
+ Unknown = 0,
15
+ Cancelled = 1,
16
+
17
+ InvalidArgument = 100,
18
+ NotFound = 101,
19
+ AlreadyExists = 102,
20
+ AccessDenied = 103,
21
+ NotDirectory = 104,
22
+ IsDirectory = 105,
23
+ DirectoryNotEmpty = 106,
24
+
25
+ NotConnected = 200,
26
+ ConnectionRefused = 201,
27
+ TimedOut = 202,
28
+
29
+ Busy = 300,
30
+ NoSpace = 301,
31
+ Io = 302,
32
+ };
33
+
34
+ class SmbErrorMapper {
35
+ public:
36
+ static int normalizeErrnoCode(int resultCode) {
37
+ if (resultCode == 0) {
38
+ return 0;
39
+ }
40
+ return resultCode < 0 ? -resultCode : resultCode;
41
+ }
42
+
43
+ static int fromErrnoResult(int resultCode) { return fromErrno(normalizeErrnoCode(resultCode)); }
44
+
45
+ static int fromErrnoOrMessage(int errnoCode, const std::string& errorMessage) {
46
+ const int mappedFromErrno = fromErrno(errnoCode);
47
+ if (mappedFromErrno != static_cast<int>(SmbErrorCode::Unknown)) {
48
+ return mappedFromErrno;
49
+ }
50
+
51
+ return fromMessage(errorMessage);
52
+ }
53
+
54
+ static int fromErrno(int errnoCode) {
55
+ switch (errnoCode) {
56
+ case 0:
57
+ return static_cast<int>(SmbErrorCode::Unknown);
58
+ case ECANCELED:
59
+ return static_cast<int>(SmbErrorCode::Cancelled);
60
+ case EINVAL:
61
+ return static_cast<int>(SmbErrorCode::InvalidArgument);
62
+ case ENOENT:
63
+ return static_cast<int>(SmbErrorCode::NotFound);
64
+ case EEXIST:
65
+ return static_cast<int>(SmbErrorCode::AlreadyExists);
66
+ case EACCES:
67
+ case EPERM:
68
+ return static_cast<int>(SmbErrorCode::AccessDenied);
69
+ case ENOTDIR:
70
+ return static_cast<int>(SmbErrorCode::NotDirectory);
71
+ case EISDIR:
72
+ return static_cast<int>(SmbErrorCode::IsDirectory);
73
+ case ENOTEMPTY:
74
+ return static_cast<int>(SmbErrorCode::DirectoryNotEmpty);
75
+ case ENOTCONN:
76
+ case EHOSTUNREACH:
77
+ case EPIPE:
78
+ #ifdef ENETRESET
79
+ case ENETRESET:
80
+ #endif
81
+ return static_cast<int>(SmbErrorCode::NotConnected);
82
+ case ECONNREFUSED:
83
+ return static_cast<int>(SmbErrorCode::ConnectionRefused);
84
+ case ETIMEDOUT:
85
+ return static_cast<int>(SmbErrorCode::TimedOut);
86
+ case EBUSY:
87
+ return static_cast<int>(SmbErrorCode::Busy);
88
+ case ENOSPC:
89
+ return static_cast<int>(SmbErrorCode::NoSpace);
90
+ case EIO:
91
+ return static_cast<int>(SmbErrorCode::Io);
92
+ default:
93
+ return static_cast<int>(SmbErrorCode::Unknown);
94
+ }
95
+ }
96
+
97
+ private:
98
+ static int fromMessage(const std::string& errorMessage) {
99
+ if (errorMessage.empty()) {
100
+ return static_cast<int>(SmbErrorCode::Unknown);
101
+ }
102
+
103
+ std::string upper = errorMessage;
104
+ std::transform(upper.begin(), upper.end(), upper.begin(), [](unsigned char c) { return static_cast<char>(std::toupper(c)); });
105
+
106
+ if (const auto ntStatus = extractNtStatusHex(upper); ntStatus.has_value()) {
107
+ const int mapped = fromNtStatus(*ntStatus);
108
+ if (mapped != static_cast<int>(SmbErrorCode::Unknown)) {
109
+ return mapped;
110
+ }
111
+ }
112
+
113
+ if (containsAny(upper, {"STATUS_OBJECT_NAME_COLLISION", "FILE_EXISTS", "EEXIST"})) {
114
+ return static_cast<int>(SmbErrorCode::AlreadyExists);
115
+ }
116
+
117
+ if (containsAny(upper, {"STATUS_OBJECT_NAME_NOT_FOUND", "STATUS_OBJECT_PATH_NOT_FOUND", "STATUS_NO_SUCH_FILE", "NO SUCH FILE"})) {
118
+ return static_cast<int>(SmbErrorCode::NotFound);
119
+ }
120
+
121
+ if (containsAny(upper, {"STATUS_ACCESS_DENIED", "STATUS_LOGON_FAILURE", "ACCESS_DENIED", "PERMISSION DENIED"})) {
122
+ return static_cast<int>(SmbErrorCode::AccessDenied);
123
+ }
124
+
125
+ if (contains(upper, "STATUS_NOT_A_DIRECTORY")) {
126
+ return static_cast<int>(SmbErrorCode::NotDirectory);
127
+ }
128
+
129
+ if (contains(upper, "STATUS_FILE_IS_A_DIRECTORY")) {
130
+ return static_cast<int>(SmbErrorCode::IsDirectory);
131
+ }
132
+
133
+ if (contains(upper, "STATUS_DIRECTORY_NOT_EMPTY")) {
134
+ return static_cast<int>(SmbErrorCode::DirectoryNotEmpty);
135
+ }
136
+
137
+ if (containsAny(upper, {"STATUS_CONNECTION_DISCONNECTED", "STATUS_NETWORK_NAME_DELETED", "BROKEN PIPE"})) {
138
+ return static_cast<int>(SmbErrorCode::NotConnected);
139
+ }
140
+
141
+ if (contains(upper, "STATUS_CONNECTION_REFUSED")) {
142
+ return static_cast<int>(SmbErrorCode::ConnectionRefused);
143
+ }
144
+
145
+ if (containsAny(upper, {"STATUS_IO_TIMEOUT", "TIMED OUT"})) {
146
+ return static_cast<int>(SmbErrorCode::TimedOut);
147
+ }
148
+
149
+ if (containsAny(upper, {"STATUS_SHARING_VIOLATION", "RESOURCE BUSY"})) {
150
+ return static_cast<int>(SmbErrorCode::Busy);
151
+ }
152
+
153
+ if (containsAny(upper, {"STATUS_DISK_FULL", "NO SPACE"})) {
154
+ return static_cast<int>(SmbErrorCode::NoSpace);
155
+ }
156
+
157
+ if (containsAny(upper, {"STATUS_IO_DEVICE_ERROR", "I/O"})) {
158
+ return static_cast<int>(SmbErrorCode::Io);
159
+ }
160
+
161
+ return static_cast<int>(SmbErrorCode::Unknown);
162
+ }
163
+
164
+ static int fromNtStatus(uint32_t ntStatus) {
165
+ switch (ntStatus) {
166
+ case 0xC0000034: // STATUS_OBJECT_NAME_NOT_FOUND
167
+ case 0xC000003A: // STATUS_OBJECT_PATH_NOT_FOUND
168
+ return static_cast<int>(SmbErrorCode::NotFound);
169
+ case 0xC0000035: // STATUS_OBJECT_NAME_COLLISION
170
+ return static_cast<int>(SmbErrorCode::AlreadyExists);
171
+ case 0xC0000022: // STATUS_ACCESS_DENIED
172
+ case 0xC000006D: // STATUS_LOGON_FAILURE
173
+ return static_cast<int>(SmbErrorCode::AccessDenied);
174
+ case 0xC0000103: // STATUS_NOT_A_DIRECTORY
175
+ return static_cast<int>(SmbErrorCode::NotDirectory);
176
+ case 0xC00000BA: // STATUS_FILE_IS_A_DIRECTORY
177
+ return static_cast<int>(SmbErrorCode::IsDirectory);
178
+ case 0xC0000101: // STATUS_DIRECTORY_NOT_EMPTY
179
+ return static_cast<int>(SmbErrorCode::DirectoryNotEmpty);
180
+ case 0xC00000B5: // STATUS_IO_TIMEOUT
181
+ return static_cast<int>(SmbErrorCode::TimedOut);
182
+ case 0xC000007F: // STATUS_DISK_FULL
183
+ return static_cast<int>(SmbErrorCode::NoSpace);
184
+ case 0xC00000E9: // STATUS_UNEXPECTED_IO_ERROR
185
+ case 0xC0000185: // STATUS_IO_DEVICE_ERROR / transport I/O
186
+ return static_cast<int>(SmbErrorCode::Io);
187
+ default:
188
+ return static_cast<int>(SmbErrorCode::Unknown);
189
+ }
190
+ }
191
+
192
+ static std::optional<uint32_t> extractNtStatusHex(const std::string& upperMessage) {
193
+ size_t pos = 0;
194
+ while ((pos = upperMessage.find("0X", pos)) != std::string::npos) {
195
+ size_t hexStart = pos + 2;
196
+ size_t hexEnd = hexStart;
197
+
198
+ while (hexEnd < upperMessage.size() && std::isxdigit(static_cast<unsigned char>(upperMessage[hexEnd]))) {
199
+ ++hexEnd;
200
+ }
201
+
202
+ const size_t hexLen = hexEnd - hexStart;
203
+ if (hexLen >= 6 && hexLen <= 8) {
204
+ try {
205
+ const auto parsed = static_cast<uint32_t>(std::stoul(upperMessage.substr(hexStart, hexLen), nullptr, 16));
206
+ return parsed;
207
+ } catch (...) {
208
+ }
209
+ }
210
+
211
+ pos = hexStart;
212
+ }
213
+
214
+ return std::nullopt;
215
+ }
216
+
217
+ static bool contains(const std::string& haystack, const char* needle) { return haystack.find(needle) != std::string::npos; }
218
+
219
+ static bool containsAny(const std::string& haystack, std::initializer_list<const char*> needles) {
220
+ for (const char* needle : needles) {
221
+ if (contains(haystack, needle)) {
222
+ return true;
223
+ }
224
+ }
225
+ return false;
226
+ }
227
+ };
228
+
229
+ } // namespace react_native_smb
@@ -0,0 +1,20 @@
1
+ #pragma once
2
+
3
+ // Diagnostic logging: os_log on Apple, __android_log_print on Android, fprintf(stderr) elsewhere.
4
+
5
+ #if defined(__APPLE__)
6
+ #include <os/log.h>
7
+ namespace react_native_smb {
8
+ inline os_log_t smb_log_handle() {
9
+ static os_log_t h = os_log_create("com.cetapod.smb", "smb");
10
+ return h;
11
+ }
12
+ } // namespace react_native_smb
13
+ #define SMB_LOG(fmt, ...) os_log(::react_native_smb::smb_log_handle(), "[smb] " fmt, ##__VA_ARGS__)
14
+ #elif defined(__ANDROID__)
15
+ #include <android/log.h>
16
+ #define SMB_LOG(fmt, ...) __android_log_print(ANDROID_LOG_INFO, "smb", fmt, ##__VA_ARGS__)
17
+ #else
18
+ #include <cstdio>
19
+ #define SMB_LOG(fmt, ...) std::fprintf(stderr, "[smb] " fmt "\n", ##__VA_ARGS__)
20
+ #endif