Esempio n. 1
0
// Open the previous (current) manifest.
// If the split_vss setting changed between the previous backup and the new
// backup, do not open the previous manifest. This will have the effect of
// making the client back up everything fresh. Need to do this, otherwise
// toggling split_vss on and off will result in backups that do not work.
static int open_previous_manifest(struct manio **cmanio,
	struct sdirs *sdirs, const char *incexc, struct conf **cconfs)
{
	struct stat statp;
	if(!lstat(sdirs->cmanifest, &statp)
	  && !vss_opts_changed(sdirs, cconfs, incexc)
	  && !(*cmanio=manio_open(sdirs->cmanifest, "rb", PROTO_1)))
	{
		logp("could not open old manifest %s\n", sdirs->cmanifest);
		return -1;
	}
	return 0;
}
Esempio n. 2
0
struct manios *manios_open_phase2(struct sdirs *sdirs, man_off_t *p1pos,
	enum protocol p)
{
	struct manios *m=NULL;
	if(!(m=manios_alloc())
	  || !(m->current=manio_open(sdirs->cmanifest, "rb", p))
	  || !(m->phase1=manio_open_phase1(sdirs->phase1data, "rb", p))
	  || !(m->changed=manio_open_phase2(sdirs->changed, "ab", p))
	  || !(m->unchanged=manio_open_phase2(sdirs->unchanged, "ab", p))
	  || (p1pos && manio_seek(m->phase1, p1pos)))
		manios_close(&m);
	return m;
}
Esempio n. 3
0
struct manio *do_manio_open(const char *path, const char *mode,
	enum protocol protocol, int phase)
{
	switch(phase)
	{
		case 0: return manio_open(path, mode, protocol);
		case 1: return manio_open_phase1(path, mode, protocol);
		case 2: return manio_open_phase2(path, mode, protocol);
		default:
			fprintf(stderr,
				"Do not know how to manio_open phase %d\n",
				phase);
			fail_unless(0);
			return NULL;
	}
}
Esempio n. 4
0
static int browse_manifest_start(struct asfd *srfd, struct cstat *cstat,
	struct bu *bu, const char *browse, struct conf **confs)
{
	int ret=-1;
	char *manifest=NULL;
	struct sbuf *sb=NULL;
	struct manio *manio=NULL;

	if(!(manifest=prepend_s(bu->path,
		cstat->protocol==PROTO_1?"manifest.gz":"manifest"))
	  || !(manio=manio_open(manifest, "rb", cstat->protocol))
	  || !(sb=sbuf_alloc(cstat->protocol)))
		goto end;
	if(get_int(confs[OPT_MONITOR_BROWSE_CACHE]))
		ret=cache_load(srfd, manio, sb, cstat, bu);
	else
		ret=do_browse_manifest(srfd, manio, sb, browse);
end:
	free_w(&manifest);
	manio_close(&manio);
	sbuf_free(&sb);
	return ret;
}
Esempio n. 5
0
/* This function reads the manifest to determine whether it may be more
   efficient to just copy the data files across and unpack them on the other
   side. If it thinks it is, it will then do it.
   Return -1 on error, 1 if it copied the data across, 0 if it did not. */
int maybe_restore_spool(struct asfd *asfd, const char *manifest,
	struct sdirs *sdirs, struct bu *bu, int srestore, regex_t *regex,
	struct conf **confs, struct slist *slist,
	enum action act, enum cntr_status cntr_status)
{
	int ars;
	int ret=-1;
	struct sbuf *sb=NULL;
	struct blk *blk=NULL;
	struct manio *manio=NULL;
	uint64_t blkcount=0;
	uint64_t datcount=0;
	struct hash_weak *tmpw;
	struct hash_weak *hash_weak;
	uint64_t estimate_blks;
	uint64_t estimate_dats;
	uint64_t estimate_one_dat;
	struct sbuf *need_data=NULL;
	int last_ent_was_dir=0;
	char sig[128]="";
	const char *restore_spool=get_string(confs[OPT_RESTORE_SPOOL]);

	// If the client has no restore_spool directory, we have to fall back
	// to the stream style restore.
	if(!restore_spool) return 0;
	
	if(!(manio=manio_open(manifest, "rb", PROTO_2))
	  || !(need_data=sbuf_alloc(PROTO_2))
	  || !(sb=sbuf_alloc(PROTO_2))
	  || !(blk=blk_alloc()))
		goto end;

	while(1)
	{
		if((ars=manio_read_with_blk(manio, sb, blk, NULL))<0)
		{
			logp("Error from manio_read_async() in %s\n",
				__func__);
			goto end; // Error;
		}
		else if(ars>0)
			break; // Finished OK.

		if(!blk->got_save_path)
		{
			sbuf_free_content(sb);
			continue;
		}

		if(want_to_restore(srestore, sb, regex, confs))
		{
			blkcount++;
			if(!hash_weak_find((uint64_t)blk->savepath))
			{
				if(!hash_weak_add((uint64_t)blk->savepath))
					goto end;
				datcount++;
			}
		}

		sbuf_free_content(sb);
	}

	// FIX THIS: should read rabin_avg of a struct rconf.
	estimate_blks=blkcount*RABIN_AVG;
	estimate_one_dat=DATA_FILE_SIG_MAX*RABIN_AVG;
	estimate_dats=datcount*estimate_one_dat;
	printf("%"PRIu64 " blocks = %"PRIu64 " bytes in stream approx\n",
		blkcount, estimate_blks);
	printf("%"PRIu64 " data files = %"PRIu64 " bytes approx\n",
		datcount, estimate_dats);

	if(estimate_blks < estimate_one_dat)
	{
		printf("Stream is less than the size of a data file.\n");
		printf("Use restore stream\n");
		return 0;
	}
	else if(estimate_dats >= 90*(estimate_blks/100))
	{
		printf("Stream is more than 90%% size of data files.\n");
		printf("Use restore stream\n");
		return 0;
	}
	else
	{
		printf("Data files are less than 90%% size of stream.\n");
		printf("Use data files\n");
	}

	printf("Client is using restore_spool: %s\n", restore_spool);

	if(asfd->write_str(asfd, CMD_GEN, "restore_spool")
	  || asfd_read_expect(asfd, CMD_GEN, "restore_spool_ok"))
		goto end;

	// Send each of the data files that we found to the client.
	HASH_ITER(hh, hash_table, hash_weak, tmpw)
	{
		char msg[32];
		char path[32];
		char *fdatpath=NULL;
		snprintf(path, sizeof(path), "%014"PRIX64, hash_weak->weak);
		path[4]='/';
		path[9]='/';
		snprintf(msg, sizeof(msg), "dat=%s", path);
		printf("got: %s\n", msg);
		if(asfd->write_str(asfd, CMD_GEN, msg)) goto end;
		if(!(fdatpath=prepend_s(sdirs->data, path)))
			goto end;
		if(send_a_file(asfd, fdatpath, get_cntr(confs)))
		{
			free_w(&fdatpath);
			goto end;
		}
		free_w(&fdatpath);
	}
Esempio n. 6
0
File: list.c Progetto: ZungBang/burp
static int list_manifest(const char *fullpath)
{
    int ret=0;
    struct sbuf *sb=NULL;
    struct manio *manio=NULL;
    char *manifest_dir=NULL;
    char *last_bd_match=NULL;
    size_t bdlen=0;

    if(!(manifest_dir=prepend_s(fullpath,
                                protocol==PROTO_1?"manifest.gz":"manifest"))
            || !(manio=manio_open(manifest_dir, "rb", protocol))
            || !(sb=sbuf_alloc(protocol)))
    {
        log_and_send_oom(asfd);
        goto error;
    }

    if(browsedir) bdlen=strlen(browsedir);

    while(1)
    {
        sbuf_free_content(sb);

        switch(manio_read(manio, sb))
        {
        case 0:
            break;
        case 1:
            if(browsedir && *browsedir && !last_bd_match)
                asfd_write_wrapper_str(asfd,
                                       CMD_ERROR,
                                       "directory not found");
            goto end; // Finished OK.
        default:
            goto error;
        }

        if(protocol==PROTO_2 && sb->endfile.buf)
            continue;
        if(sbuf_is_metadata(sb))
            continue;

        if(write_status(CNTR_STATUS_LISTING, sb->path.buf, cntr))
            goto error;

        if(browsedir)
        {
            int r;
            if((r=check_browsedir(browsedir,
                                  sb, bdlen, &last_bd_match))<0)
                goto error;
            if(!r) continue;
        }

        if(regex && !regex_check(regex, sb->path.buf))
            continue;

        if(asfd_write_wrapper(asfd, &sb->attr)
                || asfd_write_wrapper(asfd, &sb->path))
            goto error;
        if(sbuf_is_link(sb)
                && asfd_write_wrapper(asfd, &sb->link))
            goto error;
    }

error:
    ret=-1;
end:
    sbuf_free(&sb);
    free_w(&manifest_dir);
    manio_close(&manio);
    free_w(&last_bd_match);
    return ret;
}
Esempio n. 7
0
static int restore_stream(struct asfd *asfd, struct sdirs *sdirs,
        struct slist *slist, struct bu *bu, const char *manifest,
	regex_t *regex, int srestore, struct conf **cconfs, enum action act,
        enum cntr_status cntr_status)
{
	int ret=-1;
	int last_ent_was_dir=0;
	struct sbuf *sb=NULL;
	struct iobuf *rbuf=asfd->rbuf;
	struct manio *manio=NULL;
	struct blk *blk=NULL;
	struct sbuf *need_data=NULL;
	enum protocol protocol=get_protocol(cconfs);
	struct cntr *cntr=get_cntr(cconfs);

	if(protocol==PROTO_2)
	{
		if(asfd->write_str(asfd, CMD_GEN, "restore_stream")
		  || asfd->read_expect(asfd, CMD_GEN, "restore_stream_ok")
		  || !(blk=blk_alloc()))
                	goto end;
	}

	if(!(manio=manio_open(manifest, "rb", protocol))
	  || !(need_data=sbuf_alloc(protocol))
	  || !(sb=sbuf_alloc(protocol)))
		goto end;

	while(1)
	{
		iobuf_free_content(rbuf);
		if(asfd->as->read_quick(asfd->as))
		{
			logp("read quick error\n");
			goto end;
		}
		if(rbuf->buf) switch(rbuf->cmd)
		{
			case CMD_MESSAGE:
			case CMD_WARNING:
			{
				log_recvd(rbuf, cntr, 0);
				continue;
			}
			case CMD_INTERRUPT:
				// Client wanted to interrupt the
				// sending of a file. But if we are
				// here, we have already moved on.
				// Ignore.
				continue;
			default:
				iobuf_log_unexpected(rbuf, __func__);
				goto end;
		}

		switch(manio_read_with_blk(manio,
			sb, need_data->path.buf?blk:NULL, sdirs))
		{
			case 0: break; // Keep going.
			case 1: ret=0; goto end; // Finished OK.
			default: goto end; // Error;
		}

		if(protocol==PROTO_2)
		{
			if(sb->endfile.buf)
			{
				sbuf_free_content(sb);
				continue;
			}
			if(blk->data)
			{
				if(protocol2_extra_restore_stream_bits(asfd,
					blk, slist, act, need_data,
					last_ent_was_dir, cntr)) goto end;
				continue;
			}
			sbuf_free_content(need_data);
		}

		if(want_to_restore(srestore, sb, regex, cconfs))
		{
			if(restore_ent(asfd, &sb, slist,
				bu, act, sdirs, cntr_status, cconfs,
				need_data, &last_ent_was_dir, manifest))
					goto end;
		}
		else if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb))
		{
			// Add it to the list of filedata that was not
			// restored.
			struct f_link **bucket=NULL;
			if(!linkhash_search(&sb->statp, &bucket)
			  && linkhash_add(sb->path.buf, &sb->statp, bucket))
				goto end;
		}

		sbuf_free_content(sb);
	}
end:
	blk_free(&blk);
	sbuf_free(&sb);
	sbuf_free(&need_data);
	iobuf_free_content(rbuf);
	manio_close(&manio);
	return ret;
}
Esempio n. 8
0
// 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 **cconfs,
	const char *manifest, struct slist *slist)
{
	int ret=-1;
	struct sbuf *need_data=NULL;
	int last_ent_was_dir=0;
	struct sbuf *hb=NULL;
	struct manio *manio=NULL;
	struct blk *blk=NULL;
	int pcmp;
	enum protocol protocol=get_protocol(cconfs);
	struct cntr *cntr=get_cntr(cconfs);

	if(!(manio=manio_open(manifest, "rb", protocol))
	  || !(need_data=sbuf_alloc(protocol))
	  || !(hb=sbuf_alloc(protocol)))
		goto end;

	if(protocol==PROTO_2)
	{
		  if(!(blk=blk_alloc()))
                	goto end;
	}

	while(1)
	{
		switch(manio_read_with_blk(manio,
			hb, need_data->path.buf?blk:NULL, sdirs))
		{
			case 0: break; // Keep going.
			case 1: ret=0; goto end; // Finished OK.
			default: goto end; // Error;
		}

		if(protocol==PROTO_2)
		{
			if(hb->endfile.buf)
			{
				sbuf_free_content(hb);
				continue;
			}
			if(blk->data)
			{
				if(protocol2_extra_restore_stream_bits(asfd,
					blk, slist, act, need_data,
					last_ent_was_dir, cntr)) goto end;
				continue;
			}
			sbuf_free_content(need_data);
		}

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

		if(!pcmp && (sbuf_is_filedata(hb) || sbuf_is_vssdata(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, cconfs, need_data, manifest, slist);
			// May still need to get protocol2 data.
			if(!ret && need_data->path.buf) 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_close(&manio);
	return ret;
}