8e389c03f8
Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места. Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
122 lines
3.8 KiB
C
122 lines
3.8 KiB
C
/*
|
|
* p19_overwrite_probe.c — target-проверка backup/commit/rollback copy-job.
|
|
*
|
|
* UI-policy проверяется отдельно. Здесь ошибки подаются точно между
|
|
* последним write и commit, чтобы доказать сохранность старого target.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <conio.h>
|
|
#include <sprinter_mem.h>
|
|
#include "sc_copy.h"
|
|
|
|
static ScCopyJob job;
|
|
static int result_fd = -1;
|
|
static uint8_t failures;
|
|
|
|
static void log_text(const char *text)
|
|
{
|
|
const char *end = text;
|
|
uint16_t length;
|
|
|
|
cputs(text);
|
|
while (*end != '\0') end++;
|
|
length = (uint16_t)(end - text);
|
|
if (result_fd >= 0) (void)write(result_fd, text, length);
|
|
}
|
|
|
|
static void check(uint8_t condition, const char *name)
|
|
{
|
|
log_text(condition ? "PASS " : "FAIL ");
|
|
if (!condition) failures++;
|
|
log_text(name);
|
|
log_text("\r\n");
|
|
}
|
|
|
|
static int copy_file(const char *source_name, const char *target_name,
|
|
uint32_t size, uint8_t page, uint8_t replace)
|
|
{
|
|
int step;
|
|
|
|
if (sc_copy_begin_policy(&job, "D:\\SOURCE", "D:\\TARGET",
|
|
source_name, target_name, size, page,
|
|
replace) != 0) return SC_COPY_STEP_ERROR;
|
|
do {
|
|
step = sc_copy_step(&job);
|
|
} while (step == SC_COPY_STEP_MORE);
|
|
return step;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
uint16_t total_before = 0u;
|
|
uint16_t free_before = 0u;
|
|
uint16_t total_after = 0u;
|
|
uint16_t free_after = 0u;
|
|
uint8_t block;
|
|
uint8_t page;
|
|
int step;
|
|
|
|
textattr(0x07u);
|
|
clrscr_attr(0x07u);
|
|
cputs("P19 transactional overwrite\r\n\r\n");
|
|
result_fd = open("D:\\RESULT.TXT", O_WRONLY | O_CREAT | O_TRUNC);
|
|
mem_info(&total_before, &free_before);
|
|
block = mem_alloc_pages(1u);
|
|
if (block == 0u) return 1;
|
|
page = mem_get_page(block, 0u);
|
|
|
|
errno = 0;
|
|
step = sc_copy_begin(&job, "D:\\SOURCE", "D:\\TARGET",
|
|
"NORMAL.BIN", 4097ul, page);
|
|
check(step != 0 && job.error == EEXIST,
|
|
"default still refuses existing target");
|
|
|
|
step = copy_file("NORMAL.BIN", "NORMAL.BIN", 4097ul, page, 1u);
|
|
check(step == SC_COPY_STEP_DONE && job.committed,
|
|
"overwrite commits through backup");
|
|
|
|
step = copy_file("READONLY.BIN", "READONLY.BIN", 8193ul, page, 1u);
|
|
check(step == SC_COPY_STEP_DONE && job.committed &&
|
|
(job.existing_attr & 1u), "explicit readonly overwrite");
|
|
|
|
step = copy_file("COLLIDE.BIN", "COLLIDE.BIN", 4096ul, page, 1u);
|
|
check(step == SC_COPY_STEP_DONE && job.committed,
|
|
"pre-existing backup name skipped");
|
|
|
|
step = copy_file("ABSENT.BIN", "ABSENT.BIN", 17ul, page, 1u);
|
|
check(step == SC_COPY_STEP_DONE && job.committed,
|
|
"replace policy accepts vanished target");
|
|
|
|
step = copy_file("ABSENT.BIN", "RENAMED.BIN", 17ul, page, 0u);
|
|
check(step == SC_COPY_STEP_DONE && job.committed,
|
|
"distinct destination name");
|
|
|
|
step = sc_copy_begin_policy(&job, "D:\\SOURCE", "D:\\TARGET",
|
|
"ROLLBACK.BIN", "ROLLBACK.BIN",
|
|
4096ul, page, 1u);
|
|
if (step == 0) step = sc_copy_step(&job);
|
|
if (step == SC_COPY_STEP_MORE) {
|
|
(void)close(job.temp_fd);
|
|
job.temp_fd = -1;
|
|
(void)unlink(job.temp_path);
|
|
step = sc_copy_step(&job);
|
|
}
|
|
check(step == SC_COPY_STEP_ERROR && !job.committed,
|
|
"rename failure rolls original target back");
|
|
|
|
mem_free_block(block);
|
|
mem_info(&total_after, &free_after);
|
|
check(total_before == total_after && free_before == free_after,
|
|
"EMM restored");
|
|
if (failures == 0u) log_text("ALL PASS\r\n");
|
|
if (result_fd >= 0) (void)close(result_fd);
|
|
cputs("\r\nPress Enter to return to DSS.\r\n");
|
|
while (kbhit()) (void)getkey();
|
|
(void)getkey();
|
|
return failures;
|
|
}
|