7 ex__file__copy_8c
gullradriel edited this page 2026-10-29 20:54:40 +01:00

examples/ex_file_copy.c

Functions

Name
int there(const char * path)
does a file exist
int main(void )
void expect_true(const char * what, int ok)
report a check

Attributes

Name
int failures
record one check

Functions Documentation

function there

static int there(
    const char * path
)

does a file exist

function main

int main(
    void 
)

function expect_true

static void expect_true(
    const char * what,
    int ok
)

report a check

Attributes Documentation

variable failures

static int failures = 0;

record one check

Source code



#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "nilorea/n_common.h"
#include "nilorea/n_files.h"
#include "nilorea/n_log.h"

static int failures = 0;

static void expect_true(const char* what, int ok) {
    if (!ok) {
        n_log(LOG_ERR, "FAIL: %s", what);
        failures++;
    }
}

static int there(const char* path) {
    FILE* f = fopen(path, "rb");

    if (!f) return 0;
    fclose(f);
    return 1;
}

int main(void) {
    const char* tmp = getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp";
    char src[512], dst[512], part[520], other[512];
    size_t copied = 0, i = 0;
    FILE* f = NULL;

    set_log_level(LOG_NOTICE);
    snprintf(src, sizeof(src), "%s/ex_file_copy_%d.src", tmp, (int)getpid());
    snprintf(dst, sizeof(dst), "%s/ex_file_copy_%d.dst", tmp, (int)getpid());
    snprintf(part, sizeof(part), "%s.part", dst);
    snprintf(other, sizeof(other), "%s/ex_file_copy_%d.other", tmp, (int)getpid());

    /* A little over three blocks, so the loop turns and the tail is short. */
    f = fopen(src, "wb");
    if (!f) return 1;
    for (i = 0; i < 800000; i++) fputc((int)((i * 7 + i / 13) & 0xff), f);
    fclose(f);

    expect_true("a file is copied", n_file_copy_verified(src, dst, &copied) == TRUE);
    expect_true("every byte of it", copied == 800000);
    expect_true("the copy is equal", n_file_same_content(src, dst) == TRUE);
    expect_true("no part file is left", !there(part));
    expect_true("an existing copy is not replaced", n_file_copy_verified(src, dst, NULL) == FALSE);
    expect_true("and is still equal after the refusal", n_file_same_content(src, dst) == TRUE);

    /* Same size, one byte different. */
    f = fopen(other, "wb");
    if (f) {
        for (i = 0; i < 800000; i++) fputc(i == 500000 ? 0 : (int)((i * 7 + i / 13) & 0xff), f); /* 29 there in the original */
        fclose(f);
    }
    expect_true("one byte different is different", n_file_same_content(src, other) == FALSE);
    remove(other);

    remove(dst);
    expect_true("a missing source fails", n_file_copy_verified(other, dst, NULL) == FALSE);
    expect_true("and leaves nothing", !there(dst) && !there(part));
    expect_true("a NULL is refused", n_file_copy_verified(NULL, dst, NULL) == FALSE);

    {
        /* Room where the file was written, read through the file and
         * through its folder: one filesystem, so the same within what other
         * processes write between the two calls. */
        uint64_t by_file = 0, by_folder = 0, gone = 1;
        char missing[600];

        expect_true("free space through a file", n_file_free_space(src, &by_file) == TRUE && by_file > 0);
        expect_true("free space through its folder", n_file_free_space(tmp, &by_folder) == TRUE && by_folder > 0);
        expect_true("the same filesystem, the same room",
                    (by_file > by_folder ? by_file - by_folder : by_folder - by_file) < ((uint64_t)64 << 20));
        snprintf(missing, sizeof(missing), "%s/ex_file_copy_%d.none/below", tmp, (int)getpid());
        expect_true("a path that is not there fails", n_file_free_space(missing, &gone) == FALSE && gone == 0);
        expect_true("a NULL is refused", n_file_free_space(NULL, &gone) == FALSE);
        n_log(LOG_NOTICE, "free space in %s: %llu MB", tmp, (unsigned long long)(by_folder >> 20));
    }

    remove(src);
    remove(dst);
    n_log(LOG_NOTICE, "ex_file_copy: %s", failures ? "FAILED" : "ok");
    return failures ? 1 : 0;
}