diff --git a/src/media_delivery/file_transfer.c b/src/media_delivery/file_transfer.c index e19f893d6..a2c5211dc 100644 --- a/src/media_delivery/file_transfer.c +++ b/src/media_delivery/file_transfer.c @@ -34,6 +34,7 @@ struct file_transfer_op { struct file_transfer* ft; uint64_t group, peer, size, offset, progress_tb, request_tb; uint8_t tid[16], object[16]; + char path[1024]; /* Конкретная локальная копия, независимо от UUID содержимого. */ int receiving, up; FILE* file; struct CONN_MGR_HANDLE* cm; @@ -174,7 +175,8 @@ static void ft_tick(void* arg) { /* Добавить операцию до conn_mgr_open; callbacks CM используют уже живой owner. */ static struct file_transfer_op* ft_open(struct file_transfer* ft, uint64_t group, uint64_t peer, const uint8_t object[16], uint64_t size, const char* path, int receiving) { - if (!ft || ft->closing || !group || !peer || !object || !path || !size || size > INT64_MAX || ft->count >= FT_MAX_OPS) { + if (!ft || ft->closing || !group || !peer || !object || !path || strlen(path) >= 1024 || + !size || size > INT64_MAX || ft->count >= FT_MAX_OPS) { DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "file_transfer: invalid request or operation limit size=%llu", (unsigned long long)size); return NULL; @@ -183,6 +185,7 @@ static struct file_transfer_op* ft_open(struct file_transfer* ft, uint64_t group if (!op) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "file_transfer: operation allocation failed"); return NULL; } op->ft = ft; op->group = group; op->peer = peer; op->size = size; op->receiving = receiving; memcpy(op->object, object, 16); + snprintf(op->path, sizeof(op->path), "%s", path); op->file = fopen(path, receiving ? "wb" : "rb"); if (!op->file) { DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "file_transfer: open failed path=%s: %s", path, strerror(errno)); @@ -341,3 +344,15 @@ void file_transfer_cancel_object(struct file_transfer* ft, const uint8_t object[ ft_finish(found, -2); } } + +void file_transfer_cancel_path(struct file_transfer* ft, const char* path) { + if (!ft || !path) return; + for (;;) { + struct file_transfer_op* found = NULL; + for (struct file_transfer_op* op = ft->ops; op; op = op->next) + if (!strcmp(op->path, path)) { found = op; break; } + if (!found) break; + DEBUG_DEBUG(DEBUG_CATEGORY_MEDIA, "file_transfer: revoke copy peer=%llu path=%s", (unsigned long long)found->peer, path); + ft_finish(found, -2); + } +} diff --git a/src/media_delivery/file_transfer.h b/src/media_delivery/file_transfer.h index 3c25d1ecb..7550f5d7f 100644 --- a/src/media_delivery/file_transfer.h +++ b/src/media_delivery/file_transfer.h @@ -47,5 +47,8 @@ void file_transfer_cancel(struct file_transfer_op* op); /* Отозвать все операции объекта во всех группах (TTL/delete); ft=NULL допустим, object обязателен. * callbacks приёма вызываются синхронно с -2, при ошибке fclose — с -1. */ void file_transfer_cancel_object(struct file_transfer* ft, const uint8_t object[16]); +/* Отменить операции именно этого локального пути. Совмещённые endpoint/custody + * одного UUID имеют разные файлы; отзыв одного не затрагивает другую копию. */ +void file_transfer_cancel_path(struct file_transfer* ft, const char* path); #endif