do not edit — generated by btf.
git.druid.rocksindexdruid520qsrc/snap.c

src/snap.c


#include "config.h"
 
#ifdef OS_NETBSD_C
#define _NETBSD_SOURCE 1
#endif
#define _POSIX_C_SOURCE 200809L
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "q.h"
 
/* the buffer snap_sort's comparator sorts against -- qsort's comparator
 * takes no context, so the current snap's buffer is parked in file-scope
 * static for the duration of the sort. */
static const char* g_sortbuf;
 
static int
cmp_off(const void* a, const void* b)
{
	const long* ia = (const long*)a;
	const long* ib = (const long*)b;
 
	return strcmp(g_sortbuf + *ia, g_sortbuf + *ib);
}
 
void
snap_init(struct snap* s)
{
	s->buf = NULL;
	s->cap = 0;
	s->len = 0;
	s->idx = NULL;
	s->icap = 0;
	s->n = 0;
}
 
void
snap_add(struct snap* s, const char* rel)
{
	size_t n = strlen(rel);
	long need;
 
	if(s->n >= MAXPATHS)
	{
		die("too many paths in snapshot (increase MAXPATHS)");
		return;
	}
	if((size_t)s->len + n + 1 > (size_t)MAXSNAP)
	{
		die("snapshot too large (increase MAXSNAP)");
		return;
	}
	need = s->len + (long)n + 1;
	if(need > s->cap)
	{
		long ncap = s->cap;
		char* nb;
 
		if(ncap < 4096)
		{
			ncap = 4096;
		}
		while(ncap < need)
		{
			ncap = ncap + ncap;
		}
		nb = (char*)realloc(s->buf, (size_t)ncap);
		if(nb == NULL)
		{
			die("out of memory");
			return;
		}
		s->buf = nb;
		s->cap = ncap;
	}
	if(s->n >= s->icap)
	{
		long nicap = s->icap;
		long* nidx;
 
		if(nicap < 1024)
		{
			nicap = 1024;
		}
		while(nicap <= s->n)
		{
			nicap = nicap + nicap;
		}
		nidx = (long*)realloc(s->idx, (size_t)nicap * sizeof(s->idx[0]));
		if(nidx == NULL)
		{
			die("out of memory");
			return;
		}
		s->idx = nidx;
		s->icap = nicap;
	}
	memcpy(s->buf + s->len, rel, n);
	s->buf[s->len + (long)n] = '\0';
	s->idx[s->n] = s->len;
	s->len = s->len + (long)n + 1;
	s->n = s->n + 1;
}
 
void
snap_sort(struct snap* s)
{
	g_sortbuf = s->buf;
	qsort(s->idx, (size_t)s->n, sizeof(s->idx[0]), cmp_off);
}
 
const char*
snap_path(const struct snap* s, long i)
{
	return s->buf + s->idx[i];
}
 
long
snap_has(const struct snap* s, const char* rel)
{
	long lo = 0;
	long hi = s->n - 1;
 
	while(lo <= hi)
	{
		long mid = lo + (hi - lo) / 2;
		int c = strcmp(rel, snap_path(s, mid));
 
		if(c == 0)
		{
			return 1;
		}
		if(c < 0)
		{
			hi = mid - 1;
		}
		else
		{
			lo = mid + 1;
		}
	}
	return 0;
}
 
/* load a manifest (one path per line) into a snap; -1 if missing (the
 * caller treats that as empty), and a die (via snap_add) if too large. */
long
snap_readfile(struct snap* s, const char* path)
{
	FILE* f;
	char line[MAXPATH];
	long n = 0;
 
	f = fopen(path, "rb");
	if(f == NULL)
	{
		return -1;
	}
	while(fgets(line, (int)sizeof(line), f) != NULL)
	{
		size_t len = strlen(line);
 
		if(len > 0 && line[len - 1] == '\n')
		{
			line[len - 1] = '\0';
		}
		if(line[0] != '\0')
		{
			snap_add(s, line);
			n = n + 1;
		}
	}
	fclose(f);
	return n;
}
 
void
snap_writefile(const struct snap* s, const char* path)
{
	FILE* f;
	long i;
 
	f = fopen(path, "wb");
	if(f == NULL)
	{
		die("failed writing manifest");
		return;
	}
	for(i = 0; i < s->n; i = i + 1)
	{
		fputs(snap_path(s, i), f);
		fputc('\n', f);
	}
	fclose(f);
}
 
void
snap_free(struct snap* s)
{
	free(s->buf);
	free(s->idx);
	s->buf = NULL;
	s->idx = NULL;
	s->cap = 0;
	s->icap = 0;
	s->len = 0;
	s->n = 0;
}
 
/* the manifest a package owns after an install/update: every path now
 * present that either (a) this package already owned before (still
 * there), or (b) appeared during the operation (in after, not before).
 * for a fresh add, old is empty and this reduces to after - before. */
void
manifest_diff(const struct snap* before, const struct snap* after,
    const struct snap* old, struct snap* out)
{
	long i;
 
	for(i = 0; i < after->n; i = i + 1)
	{
		const char* p = snap_path(after, i);
 
		if(snap_has(old, p) || !snap_has(before, p))
		{
			snap_add(out, p);
		}
	}
}
powered by btf.