Blame src/arbits/slbt_archive_ctx.c

7bab5a
/*******************************************************************/
7bab5a
/*  slibtool: a skinny libtool implementation, written in C        */
7bab5a
/*  Copyright (C) 2016--2024  SysDeer Technologies, LLC            */
7bab5a
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
7bab5a
/*******************************************************************/
7bab5a
7bab5a
#include <stdint.h>
7bab5a
#include <stddef.h>
7bab5a
#include <stdlib.h>
7bab5a
#include <string.h>
7bab5a
#include <sys/mman.h>
7bab5a
7bab5a
#include <slibtool/slibtool.h>
7bab5a
#include "slibtool_driver_impl.h"
7bab5a
#include "slibtool_errinfo_impl.h"
7bab5a
7bab5a
static int slbt_map_raw_archive(
7bab5a
	const struct slbt_driver_ctx *	dctx,
7bab5a
	int				fd,
7bab5a
	const char *			path,
7bab5a
	int				prot,
7bab5a
	struct slbt_raw_archive *	map)
7bab5a
{
7bab5a
	struct slbt_input mapinfo = {0,0};
7bab5a
7bab5a
	if (slbt_map_input(dctx,fd,path,prot,&mapinfo) < 0)
7bab5a
		return SLBT_NESTED_ERROR(dctx);
7bab5a
7bab5a
	if (mapinfo.size == 0)
7bab5a
		return SLBT_CUSTOM_ERROR(
7bab5a
			dctx,
7bab5a
			SLBT_ERR_AR_EMPTY_FILE);
7bab5a
7bab5a
	map->map_addr = mapinfo.addr;
7bab5a
	map->map_size = mapinfo.size;
7bab5a
7bab5a
	return 0;
7bab5a
}
7bab5a
7bab5a
static int slbt_unmap_raw_archive(struct slbt_raw_archive * map)
7bab5a
{
7bab5a
	struct slbt_input mapinfo;
7bab5a
7bab5a
	mapinfo.addr = map->map_addr;
7bab5a
	mapinfo.size = map->map_size;
7bab5a
7bab5a
	return slbt_unmap_input(&mapinfo);
7bab5a
}
7bab5a
7bab5a
static int slbt_free_archive_ctx_impl(struct slbt_archive_ctx_impl * ctx, int ret)
7bab5a
{
7bab5a
	if (ctx) {
7bab5a
		slbt_free_archive_meta(ctx->meta);
7bab5a
		slbt_unmap_raw_archive(&ctx->map);
7bab5a
		free(ctx);
7bab5a
	}
7bab5a
7bab5a
	return ret;
7bab5a
}
7bab5a
7bab5a
int slbt_get_archive_ctx(
7bab5a
	const struct slbt_driver_ctx *	dctx,
7bab5a
	const char *			path,
7bab5a
	struct slbt_archive_ctx **		pctx)
7bab5a
{
7bab5a
	struct slbt_archive_ctx_impl *	ctx;
7bab5a
	int				prot;
7bab5a
7bab5a
	if (!(ctx = calloc(1,sizeof(*ctx))))
7bab5a
		return SLBT_BUFFER_ERROR(dctx);
7bab5a
7bab5a
	slbt_driver_set_arctx(
7bab5a
		dctx,0,path);
7bab5a
7bab5a
	prot = (dctx->cctx->actflags & SLBT_ACTION_MAP_READWRITE)
7bab5a
		? PROT_READ | PROT_WRITE
7bab5a
		: PROT_READ;
7bab5a
7bab5a
	if (slbt_map_raw_archive(dctx,-1,path,prot,&ctx->map))
7bab5a
		return slbt_free_archive_ctx_impl(ctx,
7bab5a
			SLBT_NESTED_ERROR(dctx));
7bab5a
7bab5a
	if (slbt_get_archive_meta(dctx,&ctx->map,&ctx->meta))
7bab5a
		return slbt_free_archive_ctx_impl(ctx,
7bab5a
			SLBT_NESTED_ERROR(dctx));
7bab5a
7bab5a
	ctx->path	= path;
7bab5a
	ctx->actx.path	= &ctx->path;
7bab5a
	ctx->actx.map	= &ctx->map;
7bab5a
	ctx->actx.meta	= ctx->meta;
7bab5a
7bab5a
	*pctx = &ctx->actx;
7bab5a
	return 0;
7bab5a
}
7bab5a
7bab5a
void slbt_free_archive_ctx(struct slbt_archive_ctx * ctx)
7bab5a
{
7bab5a
	struct slbt_archive_ctx_impl *	ictx;
7bab5a
	uintptr_t			addr;
7bab5a
7bab5a
	if (ctx) {
7bab5a
		addr = (uintptr_t)ctx - offsetof(struct slbt_archive_ctx_impl,actx);
7bab5a
		ictx = (struct slbt_archive_ctx_impl *)addr;
7bab5a
		slbt_free_archive_ctx_impl(ictx,0);
7bab5a
	}
7bab5a
}