Welcome to little lamb

Code » limb » release » tree

[release] / src / liblimb / shldata-rw.h / shldata_write.c

/* This file is part of limb                           https://lila.oss/limb
 * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
/* SPDX-License-Identifier: GPL-2.0-only */
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <limb/buffer.h>
#include <limb/buffer-shldata.h>
#include <limb/djbunix.h>
#include <limb/shldata-rw.h>
#include <limb/siovec.h>

#define SUFFIX ":tmp.limb.XXXXXX"

int
shldata_write(int bfd, const char *file, u32 magic, u64 ver,
              const char *pwd, size_t plen, unsigned algo, unsigned iter,
              int inplace, const struct iovec v[], unsigned n)
{
    int ret = 0;
    char buf[4096];
    buffer b = BUFFER_INIT(&buffer_write, -1, buf, sizeof(buf));
    size_t flen = strlen(file);
    char tmp[flen + sizeof(SUFFIX)];
    memcpy(tmp, file, flen);
    memcpy(tmp + flen, SUFFIX, sizeof(SUFFIX));

    if (!shldata_chkmagic(magic))
        return 0;

    b.fd = open_tmpat(bfd, tmp);
    if (b.fd < 0) return 0;

    if (buffer_puthdr(&b, magic, ver) < 0)
        goto err;

    buffer_shldata_ctx bsd = BUFFER_SHLDATA_ZERO;

    if (buffer_shldata_putinit(&b, pwd, plen, algo, iter, siov_len(v, n), &bsd) < 0)
        goto err;

    for (unsigned i = 0; i < n; ++i)
        if (buffer_shldata_put(&b, v[i].iov_base, v[i].iov_len, inplace, &bsd) < 0)
            goto err;

    if (buffer_shldata_putfinal(&b, &bsd) < 0 || !buffer_flush(&b)
            || renameat(bfd, tmp, bfd, file) < 0)
        goto err;

    *tmp = 0;
    ret = 1;
err:
    fd_close(b.fd);
    if (*tmp) unlinkat_void(bfd, tmp, 0);
    return ret;
}