<commit_before>#include "include.h"
#include "../cmd.h"
#include "../linkhash.h"
#include "burp1/restore.h"
#include "burp2/dpth.h"
#include "burp2/restore.h"
#include "burp2/restore_spool.h"

static enum asl_ret restore_end_func(struct asfd *asfd,
	struct conf *conf, void *param)
{
	if(!strcmp(asfd->rbuf->buf, "restoreend_ok"))
		return ASL_END_OK;
	iobuf_log_unexpected(asfd->rbuf, __func__);
	return ASL_END_ERROR;
}

static int restore_end(struct asfd *asfd, struct conf *conf)
{
	if(asfd->write_str(asfd, CMD_GEN, "restoreend")) return -1;
	return asfd->simple_loop(asfd,
		conf, NULL, __func__, restore_end_func);
}


static int srestore_matches(struct strlist *s, const char *path)
{
	int r=0;
	if(!s->flag) return 0; // Do not know how to do excludes yet.
	if((r=strncmp_w(path, s->path))) return 0; // no match
	if(!r) return 1; // exact match
	if(*(path+strlen(s->path)+1)=='/')
		return 1; // matched directory contents
	return 0; // no match
}

// Used when restore is initiated from the server.
static int check_srestore(struct conf *conf, const char *path)
{
	struct strlist *l;

	// If no includes specified, restore everything.
	if(!conf->incexcdir) return 1;

	for(l=conf->incexcdir; l; l=l->next)
		if(srestore_matches(l, path))
			return 1;
	return 0;
}

int want_to_restore(int srestore, struct sbuf *sb,
	regex_t *regex, struct conf *cconf)
{
	return (!srestore || check_srestore(cconf, sb->path.buf))
	  && check_regex(regex, sb->path.buf);
}

static int setup_cntr(struct asfd *asfd, const char *manifest,
        regex_t *regex, int srestore,
        enum action act, char status, struct conf *cconf)
{
	int ars=0;
	int ret=-1;
	gzFile zp;
	struct sbuf *sb=NULL;

// FIX THIS: this is only trying to work for burp1.
	if(cconf->protocol!=PROTO_BURP1) return 0;

	if(!(sb=sbuf_alloc(cconf))) goto end;
	if(!(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send(asfd, "could not open manifest");
		goto end;
	}
	while(1)
	{
		if((ars=sbufl_fill(sb, asfd, NULL, zp, cconf->cntr)))
		{
			if(ars<0) goto end;
			// ars==1 means end ok
			break;
		}
		else
		{
			if(want_to_restore(srestore, sb, regex, cconf))
			{
				cntr_add_phase1(cconf->cntr, sb->path.cmd, 0);
				if(sb->burp1->endfile.buf)
					cntr_add_val(cconf->cntr,
						CMD_BYTES_ESTIMATED,
						strtoull(sb->burp1->endfile.buf,
							NULL, 10), 0);
			}
		}
		sbuf_free_content(sb);
	}
	ret=0;
end:
	sbuf_free(&sb);
	gzclose_fp(&zp);
	return ret;
}

static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
	enum action act, struct sdirs *sdirs, enum cntr_status cntr_status,
	struct conf *cconf, int *need_data, const char *manifest,
	struct slist *slist);

// Used when restoring a hard link that we have not restored the destination
// for. Read through the manifest from the beginning and substitute the path
// and data to the new location.
static int hard_link_substitution(struct asfd *asfd,
	struct sbuf *sb, struct f_link *lp,
	struct bu *bu, enum action act, struct sdirs *sdirs,
	enum cntr_status cntr_status, struct conf *cconf,
	const char *manifest, struct slist *slist)
{
	int ret=-1;
	int need_data=0;
	int last_ent_was_dir=0;
	struct sbuf *hb=NULL;
	struct manio *manio=NULL;
	struct iobuf *rbuf=asfd->rbuf;
	struct blk *blk=NULL;
	struct dpth *dpth=NULL;

	if(!(manio=manio_alloc())
	  || manio_init_read(manio, manifest)
	  || !(hb=sbuf_alloc(cconf)))
		goto end;
	manio_set_protocol(manio, cconf->protocol);

	if(cconf->protocol==PROTO_BURP2)
	{
		  if(!(blk=blk_alloc())
		    || !(dpth=dpth_alloc(sdirs->data)))
                	goto end;
	}

	while(1)
	{
		iobuf_free_content(rbuf);
		switch(manio_sbuf_fill(manio, asfd, hb, blk, dpth, cconf))
		{
			case 0: break; // Keep going.
			case 1: ret=0; goto end; // Finished OK.
			default: goto end; // Error;
		}

		if(cconf->protocol==PROTO_BURP2)
		{
			if(blk->data)
			{
				if(burp2_extra_restore_stream_bits(asfd, blk,
					slist, need_data, last_ent_was_dir,
					cconf)) goto end;
				continue;
			}
			need_data=0;
		}

		if(sbuf_is_filedata(hb) && !strcmp(lp->name, hb->path.buf))
		{
			// Copy the path from sb to hb.
			free_w(&hb->path.buf);
			if(!(hb->path.buf=strdup_w(sb->path.buf, __func__)))
				goto end;
			// Should now be able to restore the original data
			// to the new location.
			ret=restore_sbuf(asfd, hb, bu, act, sdirs,
			  cntr_status, cconf, &need_data, manifest, slist);
			break;
		}

		sbuf_free_content(hb);
	}
end:
	blk_free(&blk);
	sbuf_free(&hb);
	manio_free(&manio);
	return ret;
}

static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,<commit_msg>Make restoring a hard link without restoring the original file work for burp2.<commit_after>#include "include.h"
#include "../cmd.h"
#include "../linkhash.h"
#include "burp1/restore.h"
#include "burp2/dpth.h"
#include "burp2/restore.h"
#include "burp2/restore_spool.h"

static enum asl_ret restore_end_func(struct asfd *asfd,
	struct conf *conf, void *param)
{
	if(!strcmp(asfd->rbuf->buf, "restoreend_ok"))
		return ASL_END_OK;
	iobuf_log_unexpected(asfd->rbuf, __func__);
	return ASL_END_ERROR;
}

static int restore_end(struct asfd *asfd, struct conf *conf)
{
	if(asfd->write_str(asfd, CMD_GEN, "restoreend")) return -1;
	return asfd->simple_loop(asfd,
		conf, NULL, __func__, restore_end_func);
}


static int srestore_matches(struct strlist *s, const char *path)
{
	int r=0;
	if(!s->flag) return 0; // Do not know how to do excludes yet.
	if((r=strncmp_w(path, s->path))) return 0; // no match
	if(!r) return 1; // exact match
	if(*(path+strlen(s->path)+1)=='/')
		return 1; // matched directory contents
	return 0; // no match
}

// Used when restore is initiated from the server.
static int check_srestore(struct conf *conf, const char *path)
{
	struct strlist *l;

	// If no includes specified, restore everything.
	if(!conf->incexcdir) return 1;

	for(l=conf->incexcdir; l; l=l->next)
		if(srestore_matches(l, path))
			return 1;
	return 0;
}

int want_to_restore(int srestore, struct sbuf *sb,
	regex_t *regex, struct conf *cconf)
{
	return (!srestore || check_srestore(cconf, sb->path.buf))
	  && check_regex(regex, sb->path.buf);
}

static int setup_cntr(struct asfd *asfd, const char *manifest,
        regex_t *regex, int srestore,
        enum action act, char status, struct conf *cconf)
{
	int ars=0;
	int ret=-1;
	gzFile zp;
	struct sbuf *sb=NULL;

// FIX THIS: this is only trying to work for burp1.
	if(cconf->protocol!=PROTO_BURP1) return 0;

	if(!(sb=sbuf_alloc(cconf))) goto end;
	if(!(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send(asfd, "could not open manifest");
		goto end;
	}
	while(1)
	{
		if((ars=sbufl_fill(sb, asfd, NULL, zp, cconf->cntr)))
		{
			if(ars<0) goto end;
			// ars==1 means end ok
			break;
		}
		else
		{
			if(want_to_restore(srestore, sb, regex, cconf))
			{
				cntr_add_phase1(cconf->cntr, sb->path.cmd, 0);
				if(sb->burp1->endfile.buf)
					cntr_add_val(cconf->cntr,
						CMD_BYTES_ESTIMATED,
						strtoull(sb->burp1->endfile.buf,
							NULL, 10), 0);
			}
		}
		sbuf_free_content(sb);
	}
	ret=0;
end:
	sbuf_free(&sb);
	gzclose_fp(&zp);
	return ret;
}

static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
	enum action act, struct sdirs *sdirs, enum cntr_status cntr_status,
	struct conf *cconf, int *need_data, const char *manifest,
	struct slist *slist);

// Used when restoring a hard link that we have not restored the destination
// for. Read through the manifest from the beginning and substitute the path
// and data to the new location.
static int hard_link_substitution(struct asfd *asfd,
	struct sbuf *sb, struct f_link *lp,
	struct bu *bu, enum action act, struct sdirs *sdirs,
	enum cntr_status cntr_status, struct conf *cconf,
	const char *manifest, struct slist *slist)
{
	int ret=-1;
	int need_data=0;
	int last_ent_was_dir=0;
	struct sbuf *hb=NULL;
	struct manio *manio=NULL;
	struct blk *blk=NULL;
	struct dpth *dpth=NULL;
	int pcmp;

	if(!(manio=manio_alloc())
	  || manio_init_read(manio, manifest)
	  || !(hb=sbuf_alloc(cconf)))
		goto end;
	manio_set_protocol(manio, cconf->protocol);

	if(cconf->protocol==PROTO_BURP2)
	{
		  if(!(blk=blk_alloc())
		    || !(dpth=dpth_alloc(sdirs->data)))
                	goto end;
	}

	while(1)
	{
		switch(manio_sbuf_fill(manio, asfd,
			hb, need_data?blk:NULL, dpth, cconf))
		{
			case 0: break; // Keep going.
			case 1: ret=0; goto end; // Finished OK.
			default: goto end; // Error;
		}

		if(cconf->protocol==PROTO_BURP2)
		{
			if(blk->data)
			{
				if(burp2_extra_restore_stream_bits(asfd, blk,
					slist, need_data, last_ent_was_dir,
					cconf)) goto end;
				continue;
			}
			need_data=0;
		}

		pcmp=pathcmp(lp->name, hb->path.buf);

		if(!pcmp && sbuf_is_filedata(hb))
		{
			// Copy the path from sb to hb.
			free_w(&hb->path.buf);
			if(!(hb->path.buf=strdup_w(sb->path.buf, __func__)))
				goto end;
			// Should now be able to restore the original data
			// to the new location.
			ret=restore_sbuf(asfd, hb, bu, act, sdirs,
			  cntr_status, cconf, &need_data, manifest, slist);
			// May still need to get burp2 data.
			if(!ret && need_data) continue;
			break;
		}

		sbuf_free_content(hb);
		// Break out once we have gone past the entry that we are
		// interested in.
		if(pcmp<0) break;
	}
end:
	blk_free(&blk);
	sbuf_free(&hb);
	manio_free(&manio);
	return ret;
}

static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
{'fraction_non_alphanumeric': 0.1408211018932142, 'fraction_numerical': 0.009253350350989151, 'mean_word_length': 3.866977225672878, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 68, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3669696', 'n_tokens_mistral': 4071, 'n_tokens_neox': 3758, 'n_words': 954}