do not edit — generated by btf.
git.druid.rocksindexdruid520mpsrc/util.c

src/util.c


#define _POSIX_C_SOURCE 200809L
#define _NETBSD_SOURCE 1
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "mpx.h"
 
void
die(const char* msg)
{
	fprintf(stderr, "err: %s.\n", msg);
	exit(1);
}
 
long
pathfits(const char* a, const char* b)
{
	size_t an = strlen(a);
	size_t bn = strlen(b);
 
	if(bn > (size_t)MAXPATH - 16 || an > (size_t)MAXPATH - 16 - bn)
	{
		return 0;
	}
	return 1;
}
 
long
bufcat(char* dst, size_t max, size_t* off, const char* str)
{
	size_t n = strlen(str);
 
	if(*off >= max || n >= max - *off)
	{
		return 0;
	}
	memcpy(dst + *off, str, n);
	*off = *off + n;
	dst[*off] = '\0';
	return 1;
}
 
long
pathjoin(char* dst, size_t max, const char* a, const char* b)
{
	size_t off = 0;
 
	if(bufcat(dst, max, &off, a) == 0)
	{
		return 0;
	}
	if(bufcat(dst, max, &off, "/") == 0)
	{
		return 0;
	}
	if(bufcat(dst, max, &off, b) == 0)
	{
		return 0;
	}
	return 1;
}
 
/* returns bytes read (0..max), -1 if path couldn't be opened, or -2 if
 * the file holds MORE than max bytes -- fread() alone can't tell "read
 * exactly max bytes because that's the whole file" apart from "silently
 * clipped a bigger file at max", so every caller that cares about the
 * difference needs its own signal. the extra fgetc() after filling buf
 * is the cheapest way to ask "is there really nothing left": it returns
 * a real byte (not EOF) only if the file is bigger than max. */
long
readfile(const char* path, char* buf, long max)
{
	FILE* f;
	long n;
	int extra;
 
	f = fopen(path, "rb");
	if(f == NULL)
	{
		return -1;
	}
	n = (long)fread(buf, 1, (size_t)max, f);
	extra = fgetc(f);
	fclose(f);
	if(extra != EOF)
	{
		return -2;
	}
	return n;
}
 
long
writefile(const char* path, const char* buf, long n)
{
	FILE* f;
	long w;
 
	f = fopen(path, "wb");
	if(f == NULL)
	{
		return -1;
	}
	w = (long)fwrite(buf, 1, (size_t)n, f);
	fclose(f);
	if(w != n)
	{
		return -1;
	}
	return w;
}
 
void
setflags(const char* name, const char* extra)
{
	char buf[MAXVAL] = {0};
	const char* cur;
	size_t off = 0;
 
	cur = getenv(name);
	if(cur != NULL && cur[0] != '\0')
	{
		if(bufcat(buf, sizeof(buf), &off, cur) == 0
		    || bufcat(buf, sizeof(buf), &off, " ") == 0
		    || bufcat(buf, sizeof(buf), &off, extra) == 0)
		{
			die("target flags too long");
		}
	}
	else
	{
		if(bufcat(buf, sizeof(buf), &off, extra) == 0)
		{
			die("target flags too long");
		}
	}
	setenv(name, buf, 1);
}
 
void
setxenv(const char* name, const char* val)
{
	if(val != NULL && val[0] != '\0')
	{
		setenv(name, val, 1);
	}
}
 
/* like setflags(), but joins with ':' instead of a space -- for PATH-like
 * variables (PKG_CONFIG_PATH) rather than flag lists (CFLAGS/LDFLAGS). a
 * separate function rather than a parameter on setflags() itself: keeps
 * setflags()'s eight existing space-joined call sites untouched. */
void
setpath(const char* name, const char* extra)
{
	char buf[MAXVAL] = {0};
	const char* cur;
	size_t off = 0;
 
	cur = getenv(name);
	if(cur != NULL && cur[0] != '\0')
	{
		if(bufcat(buf, sizeof(buf), &off, extra) == 0
		    || bufcat(buf, sizeof(buf), &off, ":") == 0
		    || bufcat(buf, sizeof(buf), &off, cur) == 0)
		{
			die("target flags too long");
		}
	}
	else
	{
		if(bufcat(buf, sizeof(buf), &off, extra) == 0)
		{
			die("target flags too long");
		}
	}
	setenv(name, buf, 1);
}
 
/* scans the trailing NAME=VAL args of a runsh invocation (argv[4..argc))
 * for name, returning a pointer to its value or NULL if absent. used to
 * find an effective MP_PREFIX/MP_PREFIX_BASE before those args get
 * applied to the child's environment further down. */
const char*
argval(int argc, char** argv, const char* name)
{
	int ei;
	size_t namelen;
 
	namelen = strlen(name);
	for(ei = 4; ei < argc; ei = ei + 1)
	{
		if(strncmp(argv[ei], name, namelen) == 0 && argv[ei][namelen] == '=')
		{
			return argv[ei] + namelen + 1;
		}
	}
	return NULL;
}
powered by btf.