Blame src/logic/tpax_archive_write.c

fb29e1
/**************************************************************/
fb29e1
/*  tpax: a topological pax implementation                    */
fb29e1
/*  Copyright (C) 2020--2024  SysDeer Technologies, LLC       */
fb29e1
/*  Released under GPLv2 and GPLv3; see COPYING.TPAX.         */
fb29e1
/**************************************************************/
fb29e1
fb29e1
#include <tpax/tpax.h>
fb29e1
#include "tpax_driver_impl.h"
fb29e1
#include "tpax_errinfo_impl.h"
fb29e1
#include "tpax_visibility_impl.h"
fb29e1
fb29e1
static int tpax_archive_append_memory_data(
fb29e1
	int                             fdout,
fb29e1
	void *                          buf,
fb29e1
	ssize_t                         nbytes)
fb29e1
{
fb29e1
	ssize_t ret;
fb29e1
	char  * ch;
fb29e1
fb29e1
	for (ch=buf; nbytes; ch+=ret) {
fb29e1
		ret = write(fdout,ch,nbytes);
fb29e1
fb29e1
		while ((ret < 0) && (errno == EINTR))
fb29e1
			ret = write(fdout,ch,nbytes);
fb29e1
fb29e1
		if (ret < 0)
fb29e1
			return ret;
fb29e1
fb29e1
		nbytes -= ret;
fb29e1
	}
fb29e1
fb29e1
	return 0;
fb29e1
}
fb29e1
fb29e1
static int tpax_archive_append_pad(
fb29e1
	const struct tpax_driver_ctx *  dctx,
fb29e1
	int                             fdout,
fb29e1
	const struct stat *             st)
fb29e1
{
fb29e1
	int     ret;
fb29e1
	off_t   cpos;
fb29e1
	ssize_t nbytes;
fb29e1
	char    buf[512];
fb29e1
fb29e1
	nbytes  = st->st_size;
fb29e1
	nbytes += 0x1ff;
fb29e1
	nbytes |= 0x1ff;
fb29e1
	nbytes ^= 0x1ff;
fb29e1
	nbytes -= st->st_size;
fb29e1
fb29e1
	memset(buf,0,nbytes);
fb29e1
fb29e1
	cpos  = tpax_get_driver_cpos(dctx);
fb29e1
	cpos += st->st_size + nbytes;
fb29e1
fb29e1
	if (!(ret = tpax_archive_append_memory_data(fdout,buf,nbytes)))
fb29e1
		tpax_set_driver_cpos(dctx,cpos);
fb29e1
fb29e1
	return ret;
fb29e1
}
fb29e1
fb29e1
int tpax_archive_seal(const struct tpax_driver_ctx * dctx)
fb29e1
{
fb29e1
	int     fdout;
fb29e1
	off_t   cpos;
fb29e1
	ssize_t nbytes;
fb29e1
	ssize_t nwritten;
fb29e1
	ssize_t blksize;
fb29e1
	char    buf[512];
fb29e1
fb29e1
	blksize = tpax_get_archive_block_size(dctx);
fb29e1
	cpos    = tpax_get_driver_cpos(dctx);
fb29e1
fb29e1
	if (cpos % 512)
fb29e1
		return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR);
fb29e1
fb29e1
	fdout = tpax_driver_fdout(dctx);
fb29e1
	memset(buf,0,sizeof(buf));
fb29e1
fb29e1
	switch (cpos % blksize) {
fb29e1
		case 0:
fb29e1
			nbytes = cpos + blksize;
fb29e1
			break;
fb29e1
fb29e1
		default:
fb29e1
			nbytes  = cpos / blksize;
fb29e1
			nbytes *= blksize;
fb29e1
			nbytes += blksize;
fb29e1
fb29e1
			if (nbytes-cpos == 512)
fb29e1
				nbytes += blksize;
fb29e1
	}
fb29e1
fb29e1
	for (nwritten=cpos; nwritten
fb29e1
		if (tpax_archive_append_memory_data(fdout,buf,512) < 0)
fb29e1
			return TPAX_SYSTEM_ERROR(dctx);
fb29e1
fb29e1
		tpax_set_driver_cpos(dctx,nwritten);
fb29e1
	}
fb29e1
fb29e1
	(void)tpax_archive_append_pad;
fb29e1
fb29e1
	return 0;
fb29e1
}