#include "ssb.import.h" #include "ssb.h" #include #include #include #include #include typedef struct _tf_import_file_t { uv_fs_t req; uv_file file; tf_ssb_t* ssb; const char* user; const char* parent; const char* name; //uv_buf_t buf; char data[k_ssb_blob_bytes_max]; int* work_left; } tf_import_file_t; static void _tf_ssb_import_file_close(uv_fs_t* req) { tf_import_file_t* file = req->data; (*file->work_left)--; uv_fs_req_cleanup(req); free(req->data); } static void _tf_ssb_import_file_read(uv_fs_t* req) { tf_import_file_t* file = req->data; char id[k_id_base64_len]; if (req->result >= 0) { if (tf_ssb_blob_store(file->ssb, (const uint8_t*)file->data, req->result, id, sizeof(id))) { printf("Stored %s/%s as %s.\n", file->parent, file->name, id); if (strcasecmp(file->name + strlen(file->name) - strlen(".json"), ".json") == 0) { sqlite3_stmt* statement; if (sqlite3_prepare(tf_ssb_get_db(file->ssb), "INSERT OR REPLACE INTO properties (id, key, value) VALUES ($1, 'path:' || $2, $3)", -1, &statement, NULL) == SQLITE_OK) { ((char*)file->name)[strlen(file->name) - strlen(".json")] = '\0'; if (sqlite3_bind_text(statement, 1, file->user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, file->name, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 3, id, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_DONE) { printf("Registered %s path:%s as %s.\n", file->user, file->name, id); } sqlite3_finalize(statement); } } } } uv_fs_req_cleanup(req); uv_fs_close(tf_ssb_get_loop(file->ssb), req, file->file, _tf_ssb_import_file_close); } static void _tf_ssb_import_file_open(uv_fs_t* req) { tf_import_file_t* file = req->data; file->file = req->result; uv_fs_req_cleanup(req); uv_fs_read(tf_ssb_get_loop(file->ssb), req, file->file, &(uv_buf_t) { .base = file->data, .len = k_ssb_blob_bytes_max }, 1, 0, _tf_ssb_import_file_read); } typedef struct _tf_import_t { tf_ssb_t* ssb; const char* user; const char* parent; uv_fs_t req; int work_left; } tf_import_t; static void _tf_ssb_import_scandir(uv_fs_t* req) { tf_import_t* import = req->data; uv_dirent_t ent; while (uv_fs_scandir_next(req, &ent) == 0) { size_t len = strlen(import->parent) + strlen(ent.name) + 2; char* path = malloc(len); snprintf(path, len, "%s/%s", import->parent, ent.name); if (ent.type == UV_DIRENT_DIR) { tf_ssb_import(import->ssb, import->user, path); } else { size_t size = sizeof(tf_import_file_t) + strlen(import->parent) +1 + strlen(ent.name) + 1; tf_import_file_t* file = malloc(size); memset(file, 0, size); file->ssb = import->ssb; file->user = import->user; file->parent = (void*)(file + 1); file->name = file->parent + strlen(import->parent) + 1; file->req.data = file; file->work_left = &import->work_left; memcpy((char*)file->parent, import->parent, strlen(import->parent) + 1); memcpy((char*)file->name, ent.name, strlen(ent.name) + 1); import->work_left++; int r = uv_fs_open(tf_ssb_get_loop(import->ssb), &file->req, path, 0, 0, _tf_ssb_import_file_open); if (r < 0) { printf("Failed to open %s: %s.\n", path, uv_strerror(r)); free(file); import->work_left--; } } free(path); } import->work_left--; } void tf_ssb_import(tf_ssb_t* ssb, const char* user, const char* path) { tf_import_t import = { .ssb = ssb, .user = user, .parent = path, .work_left = 1, }; import.req.data = &import; int r = uv_fs_scandir(tf_ssb_get_loop(ssb), &import.req, path, 0, _tf_ssb_import_scandir); if (r) { printf("Failed to scan directory %s: %s.", path, uv_strerror(r)); } while (import.work_left > 0) { uv_run(tf_ssb_get_loop(ssb), UV_RUN_ONCE); } uv_fs_req_cleanup(&import.req); }