Blame src/driver/slbt_symlist_ctx.c

d42469
/*******************************************************************/
d42469
/*  slibtool: a skinny libtool implementation, written in C        */
d42469
/*  Copyright (C) 2016--2024  SysDeer Technologies, LLC            */
d42469
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
d42469
/*******************************************************************/
d42469
d42469
#include <ctype.h>
d42469
#include <stdint.h>
d42469
#include <stddef.h>
d42469
#include <stdlib.h>
d42469
#include <string.h>
d42469
#include <sys/mman.h>
d42469
d42469
#include <slibtool/slibtool.h>
d42469
#include "slibtool_driver_impl.h"
d42469
#include "slibtool_errinfo_impl.h"
d42469
d42469
static int slbt_lib_free_symlist_ctx_impl(
d42469
	struct slbt_symlist_ctx_impl *  ctx,
d42469
	struct slbt_input *             mapinfo,
d42469
	int                             ret)
d42469
{
d42469
	if (mapinfo)
d42469
		slbt_fs_unmap_input(mapinfo);
d42469
d42469
	if (ctx) {
d42469
		if (ctx->pathbuf)
d42469
			free(ctx->pathbuf);
d42469
d42469
		if (ctx->symstrs)
d42469
			free(ctx->symstrs);
d42469
d42469
		if (ctx->symstrv)
d42469
			free(ctx->symstrv);
d42469
d42469
		free(ctx);
d42469
	}
d42469
d42469
	return ret;
d42469
}
d42469
d42469
int slbt_lib_get_symlist_ctx(
d42469
	const struct slbt_driver_ctx *  dctx,
d42469
	const char *                    path,
d42469
	struct slbt_symlist_ctx **      pctx)
d42469
{
d42469
	struct slbt_symlist_ctx_impl *  ctx;
d42469
	struct slbt_input               mapinfo;
d42469
	size_t                          nsyms;
d42469
	char *                          ch;
d42469
	char *                          cap;
d42469
	char *                          src;
d42469
	const char **                   psym;
d42469
	char                            dummy;
d42469
	bool                            fvalid;
d42469
d42469
	/* map symlist file temporarily */
d42469
	if (slbt_fs_map_input(dctx,-1,path,PROT_READ,&mapinfo) < 0)
d42469
		return SLBT_NESTED_ERROR(dctx);
d42469
d42469
	/* alloc context */
d42469
	if (!(ctx = calloc(1,sizeof(*ctx))))
d42469
		return slbt_lib_free_symlist_ctx_impl(
d42469
			ctx,&mapinfo,
d42469
			SLBT_BUFFER_ERROR(dctx));
d42469
d42469
	/* count symbols */
d42469
	src = mapinfo.size ? mapinfo.addr : &dummy;
d42469
	cap = &src[mapinfo.size];
d42469
d42469
	for (; (src
d42469
		src++;
d42469
d42469
	for (ch=src,nsyms=0; ch
d42469
		for (; (ch
d42469
			ch++;
d42469
d42469
		fvalid = false;
d42469
d42469
		for (; (ch
d42469
			fvalid = (*ch++ == '\n') || fvalid;
d42469
d42469
		if (!fvalid)
d42469
			return slbt_lib_free_symlist_ctx_impl(
d42469
				ctx,&mapinfo,
d42469
				SLBT_CUSTOM_ERROR(
d42469
					dctx,
d42469
					SLBT_ERR_FLOW_ERROR));
d42469
	}
d42469
d42469
	/* clone path, alloc string buffer and symbol vector */
d42469
	if (!(ctx->pathbuf = strdup(path)))
d42469
		return slbt_lib_free_symlist_ctx_impl(
d42469
			ctx,&mapinfo,
d42469
			SLBT_SYSTEM_ERROR(dctx,0));
d42469
d42469
	if (!(ctx->symstrs = calloc(mapinfo.size+1,1)))
d42469
		return slbt_lib_free_symlist_ctx_impl(
d42469
			ctx,&mapinfo,
d42469
			SLBT_SYSTEM_ERROR(dctx,0));
d42469
d42469
	if (!(ctx->symstrv = calloc(nsyms+1,sizeof(char *))))
d42469
		return slbt_lib_free_symlist_ctx_impl(
d42469
			ctx,&mapinfo,
d42469
			SLBT_SYSTEM_ERROR(dctx,0));
d42469
d42469
	/* copy the source to the allocated string buffer */
d42469
	memcpy(ctx->symstrs,mapinfo.addr,mapinfo.size);
d42469
	slbt_fs_unmap_input(&mapinfo);
d42469
d42469
	/* populate the symbol vector, handle whitespace */
d42469
	src = ctx->symstrs;
d42469
	cap = &src[mapinfo.size];
d42469
d42469
	for (; (src
d42469
		src++;
d42469
d42469
	for (ch=src,psym=ctx->symstrv; ch
d42469
		*psym = ch;
d42469
d42469
		for (; (ch
d42469
			ch++;
d42469
d42469
		for (; (ch
d42469
			*ch++ = '\0';
d42469
	}
d42469
d42469
	/* all done */
d42469
	ctx->dctx         = dctx;
d42469
	ctx->path         = ctx->pathbuf;
d42469
	ctx->sctx.path	  = &ctx->path;
d42469
	ctx->sctx.symstrv = ctx->symstrv;
d42469
d42469
	*pctx = &ctx->sctx;
d42469
d42469
	return 0;
d42469
}
d42469
d42469
void slbt_lib_free_symlist_ctx(struct slbt_symlist_ctx * ctx)
d42469
{
d42469
	struct slbt_symlist_ctx_impl *	ictx;
d42469
	uintptr_t			addr;
d42469
d42469
	if (ctx) {
d42469
		addr = (uintptr_t)ctx - offsetof(struct slbt_symlist_ctx_impl,sctx);
d42469
		ictx = (struct slbt_symlist_ctx_impl *)addr;
d42469
		slbt_lib_free_symlist_ctx_impl(ictx,0,0);
d42469
	}
d42469
}