create backup only when receiver found

This commit is contained in:
2026-04-25 10:46:20 +03:00
parent a2e874de85
commit 22b669fae0
6 changed files with 40 additions and 41 deletions
+2
View File
@@ -11,6 +11,7 @@ struct TransferState {
std::atomic<uint64_t> bytes_total{0}; std::atomic<uint64_t> bytes_total{0};
std::string status; std::string status;
std::string fail_reason;
mutable std::mutex status_mutex; mutable std::mutex status_mutex;
void reset() { void reset() {
@@ -19,6 +20,7 @@ struct TransferState {
connection_failed = false; connection_failed = false;
bytes_done = 0; bytes_done = 0;
bytes_total = 0; bytes_total = 0;
fail_reason.clear();
std::lock_guard<std::mutex> lock(status_mutex); std::lock_guard<std::mutex> lock(status_mutex);
status.clear(); status.clear();
} }
+3 -4
View File
@@ -1,12 +1,11 @@
#include <filesystem>
#include <string> #include <string>
namespace fs = std::filesystem; #include <switch.h>
using path = fs::path;
int transfer_files(path directory); int transfer_files(size_t index, AccountUid uid);
bool isClientTransferDone(); bool isClientTransferDone();
bool isClientTransferCancelled(); bool isClientTransferCancelled();
bool isClientConnectionFailed(); bool isClientConnectionFailed();
void cancelClientTransfer(); void cancelClientTransfer();
double getClientProgress(); double getClientProgress();
std::string getClientStatusText(); std::string getClientStatusText();
std::string getClientFailReason();
+2 -8
View File
@@ -46,18 +46,12 @@ namespace ui {
switch (opt) { switch (opt) {
case 0: { case 0: {
// Transfer selected // Transfer selected
auto backupResult = io::backup(index, g_currentUId);
if (!std::get<0>(backupResult)) {
mainApp->CreateShowDialog("Transfer", "Failed to create backup:\n" + std::get<2>(backupResult), {"OK"}, true);
break;
}
auto directory = std::filesystem::path(std::get<2>(backupResult));
{ {
auto ovl = TransferOverlay::New("Transferring save data..."); auto ovl = TransferOverlay::New("Transferring save data...");
this->titlesMenu->SetVisible(false); this->titlesMenu->SetVisible(false);
mainApp->StartOverlay(ovl); mainApp->StartOverlay(ovl);
this->LockInput(); this->LockInput();
if (transfer_files(directory) != 0) { if (transfer_files(index, g_currentUId) != 0) {
mainApp->EndOverlay(); mainApp->EndOverlay();
this->titlesMenu->SetVisible(true); this->titlesMenu->SetVisible(true);
this->UnlockInput(); this->UnlockInput();
@@ -78,7 +72,7 @@ namespace ui {
this->UnlockInput(); this->UnlockInput();
} }
if (isClientConnectionFailed()) { if (isClientConnectionFailed()) {
mainApp->CreateShowDialog("Transfer", "No receiver found.\nMake sure the other Switch is in Receive mode.", {"OK"}, true); mainApp->CreateShowDialog("Transfer", getClientFailReason(), {"OK"}, true);
} else if (isClientTransferCancelled()) { } else if (isClientTransferCancelled()) {
mainApp->CreateShowDialog("Transfer", "Transfer cancelled.", {"OK"}, true); mainApp->CreateShowDialog("Transfer", "Transfer cancelled.", {"OK"}, true);
} else { } else {
+27 -20
View File
@@ -14,6 +14,7 @@
#ifdef __SWITCH__ #ifdef __SWITCH__
#include <client.hpp> #include <client.hpp>
#include <io.hpp>
#include <switch.h> #include <switch.h>
#endif #endif
@@ -32,6 +33,7 @@ bool isClientConnectionFailed() { return g_client_state.connection_failed.loa
void cancelClientTransfer() { g_client_state.cancelled.store(true); } void cancelClientTransfer() { g_client_state.cancelled.store(true); }
double getClientProgress() { return g_client_state.progress(); } double getClientProgress() { return g_client_state.progress(); }
std::string getClientStatusText() { return g_client_state.getStatus(); } std::string getClientStatusText() { return g_client_state.getStatus(); }
std::string getClientFailReason() { return g_client_state.fail_reason; }
static bool send_all(int sock, const void* buf, size_t len) { static bool send_all(int sock, const void* buf, size_t len) {
size_t sent = 0; size_t sent = 0;
@@ -78,35 +80,52 @@ static bool sendFile(int sock, const fs::path& filepath) {
return true; return true;
} }
struct ThreadArgs { size_t index; AccountUid uid; };
static int find_server(char* server_ip); static int find_server(char* server_ip);
static void fail_connect() { static void fail_connect(const std::string& reason) {
g_client_state.fail_reason = reason;
g_client_state.connection_failed.store(true); g_client_state.connection_failed.store(true);
g_client_state.done.store(true); g_client_state.done.store(true);
} }
static void* discovery_and_send_thread(void* arg) { static void* discovery_and_send_thread(void* arg) {
fs::path directory = *static_cast<fs::path*>(arg); ThreadArgs* targs = static_cast<ThreadArgs*>(arg);
delete static_cast<fs::path*>(arg); size_t index = targs->index;
AccountUid uid = targs->uid;
delete targs;
char server_ip[INET_ADDRSTRLEN]; char server_ip[INET_ADDRSTRLEN];
if (find_server(server_ip) != 0) { if (find_server(server_ip) != 0) {
if (!g_client_state.cancelled.load()) fail_connect(); if (!g_client_state.cancelled.load())
fail_connect("No receiver found.\nMake sure the other Switch is in Receive mode.");
else
g_client_state.done.store(true); g_client_state.done.store(true);
return nullptr; return nullptr;
} }
if (g_client_state.cancelled.load()) { g_client_state.done.store(true); return nullptr; } if (g_client_state.cancelled.load()) { g_client_state.done.store(true); return nullptr; }
g_client_state.setStatus("Creating backup...");
auto backupResult = io::backup(index, uid);
if (!std::get<0>(backupResult)) {
fail_connect("Failed to create backup:\n" + std::get<2>(backupResult));
return nullptr;
}
fs::path directory = std::get<2>(backupResult);
if (g_client_state.cancelled.load()) { g_client_state.done.store(true); return nullptr; }
g_client_state.setStatus("Connecting..."); g_client_state.setStatus("Connecting...");
Socket tcp(socket(AF_INET, SOCK_STREAM, 0)); Socket tcp(socket(AF_INET, SOCK_STREAM, 0));
if (!tcp.valid()) { fail_connect(); return nullptr; } if (!tcp.valid()) { fail_connect("Failed to open socket."); return nullptr; }
sockaddr_in serv{}; sockaddr_in serv{};
serv.sin_family = AF_INET; serv.sin_family = AF_INET;
serv.sin_port = htons(proto::TCP_PORT); serv.sin_port = htons(proto::TCP_PORT);
if (inet_pton(AF_INET, server_ip, &serv.sin_addr) <= 0 || if (inet_pton(AF_INET, server_ip, &serv.sin_addr) <= 0 ||
connect(tcp, (sockaddr*)&serv, sizeof(serv)) < 0) { connect(tcp, (sockaddr*)&serv, sizeof(serv)) < 0) {
fail_connect(); fail_connect("Failed to connect to receiver.");
return nullptr; return nullptr;
} }
@@ -179,11 +198,11 @@ static int find_server(char* server_ip) {
return -1; return -1;
} }
int transfer_files(fs::path directory) { int transfer_files(size_t index, AccountUid uid) {
g_client_state.reset(); g_client_state.reset();
g_client_state.setStatus("Searching for receiver..."); g_client_state.setStatus("Searching for receiver...");
fs::path* arg = new fs::path(directory); ThreadArgs* arg = new ThreadArgs{index, uid};
pthread_t thread; pthread_t thread;
if (pthread_create(&thread, nullptr, discovery_and_send_thread, arg) != 0) { if (pthread_create(&thread, nullptr, discovery_and_send_thread, arg) != 0) {
delete arg; delete arg;
@@ -192,15 +211,3 @@ int transfer_files(fs::path directory) {
pthread_detach(thread); pthread_detach(thread);
return 0; return 0;
} }
#ifndef __SWITCH__
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <path>" << std::endl;
return 1;
}
if (transfer_files(fs::path(argv[1])) != 0) return 1;
while (!isClientTransferDone()) usleep(16000);
return 0;
}
#endif
+1
View File
@@ -176,6 +176,7 @@ std::tuple<bool, Result, std::string> io::backup(size_t index, AccountUid uid)
std::string suggestion = StringUtils::removeNotAscii(StringUtils::removeAccents(Account::username(title.userId()))); std::string suggestion = StringUtils::removeNotAscii(StringUtils::removeAccents(Account::username(title.userId())));
io::createDirectory(title.path());
std::string dstPath = title.path() + "/" + suggestion; std::string dstPath = title.path() + "/" + suggestion;
// Write to a temp dir first; rename on success so the existing backup // Write to a temp dir first; rename on success so the existing backup
-4
View File
@@ -65,10 +65,6 @@ void Title::init(u8 saveDataType, u64 id, AccountUid userID, const std::string&
} }
} }
if (!io::directoryExists(mPath)) {
io::createDirectory(mPath);
}
refreshDirectories(); refreshDirectories();
} }