mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-10-17 19:05:07 +00:00
87 lines
3.1 KiB
C++
87 lines
3.1 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
#include <development/requests.h>
|
|
|
|
#include <tactility/filesystem/fs.h>
|
|
#include <tactility/log.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
namespace {
|
|
|
|
constexpr auto* TAG = "DevelopmentSync";
|
|
|
|
bool handleStat(DevelopmentRequestContext& context, const DevelopmentFrame& frame) {
|
|
char path[FILE_MAX_PATH_STRING_LENGTH];
|
|
if (!development_requests_read_path(frame, path)) {
|
|
return development_requests_send_fail(context, "invalid path");
|
|
}
|
|
uint8_t result[9] = {};
|
|
struct stat info {};
|
|
if (stat(path, &info) == 0) {
|
|
result[0] = S_ISDIR(info.st_mode) ? DEVELOPMENT_SYNC_FILE_DIRECTORY : DEVELOPMENT_SYNC_FILE_REGULAR;
|
|
const auto size = static_cast<uint64_t>(info.st_size);
|
|
for (int i = 0; i < 8; i++) {
|
|
result[1 + i] = static_cast<uint8_t>(size >> (56 - i * 8));
|
|
}
|
|
}
|
|
return development_session_send_frame(context.session, DEVELOPMENT_FRAME_SYNC_STAT_RESULT, result, sizeof(result));
|
|
}
|
|
|
|
void handlePush(DevelopmentRequestContext& context, const DevelopmentFrame& frame) {
|
|
char path[FILE_MAX_PATH_STRING_LENGTH];
|
|
if (development_requests_read_path(frame, path)) {
|
|
development_requests_start_push(context, path, nullptr, nullptr, false);
|
|
} else {
|
|
development_requests_start_push(context, nullptr, "invalid path", nullptr, false);
|
|
}
|
|
}
|
|
|
|
bool handlePull(DevelopmentRequestContext& context, const DevelopmentFrame& frame) {
|
|
char path[FILE_MAX_PATH_STRING_LENGTH];
|
|
if (!development_requests_read_path(frame, path)) {
|
|
return development_requests_send_fail(context, "invalid path");
|
|
}
|
|
if (directory_exists(path)) {
|
|
return development_requests_send_fail(context, "is a directory");
|
|
}
|
|
FILE* file = fopen(path, "rb");
|
|
if (file == nullptr) {
|
|
return development_requests_send_fail(context, "failed to open file");
|
|
}
|
|
bool connected = true;
|
|
size_t length;
|
|
while (connected && (length = fread(context.buffer, 1, DEVELOPMENT_FRAME_PAYLOAD_MAX, file)) > 0) {
|
|
connected = development_session_send_frame(context.session, DEVELOPMENT_FRAME_DATA, context.buffer, static_cast<uint16_t>(length));
|
|
development_requests_poll_events(context);
|
|
if (*context.closeRequested) {
|
|
connected = false;
|
|
}
|
|
}
|
|
const bool failed = ferror(file) != 0;
|
|
fclose(file);
|
|
if (!connected) {
|
|
return false;
|
|
}
|
|
if (failed) {
|
|
return development_requests_send_fail(context, "failed to read file");
|
|
}
|
|
LOG_I(TAG, "Pulled %s", path);
|
|
return development_session_send_frame(context.session, DEVELOPMENT_FRAME_DONE, nullptr, 0);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool development_sync_handle(DevelopmentRequestContext& context, const DevelopmentFrame& frame) {
|
|
switch (frame.type) {
|
|
case DEVELOPMENT_FRAME_SYNC_STAT:
|
|
return handleStat(context, frame);
|
|
case DEVELOPMENT_FRAME_SYNC_PUSH:
|
|
handlePush(context, frame);
|
|
return true;
|
|
case DEVELOPMENT_FRAME_SYNC_PULL:
|
|
return handlePull(context, frame);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|