/* 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;
}