/* * p19_overwrite_probe.c — target-проверка backup/commit/rollback copy-job. * * UI-policy проверяется отдельно. Здесь ошибки подаются точно между * последним write и commit, чтобы доказать сохранность старого target. */ #include #include #include #include #include #include #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; }