Beispiel #1
0
static void get_wbuf_from_data(struct conf **confs,
	struct iobuf *wbuf, struct slist *slist, uint8_t end_flags)
{
	struct blk *blk;
	struct blist *blist=slist->blist;

	for(blk=blist->last_sent; blk; blk=blk->next)
	{
		if(blk->requested)
		{
			iobuf_set(wbuf, CMD_DATA, blk->data, blk->length);
			blk->requested=0;
			blist->last_sent=blk;
			cntr_add(get_cntr(confs), CMD_DATA, 1);
			break;
		}
		else
		{
			cntr_add_same(get_cntr(confs), CMD_DATA);
			if(end_flags&END_BLK_REQUESTS)
			{
				// Force onwards when the server has said that
				// there are no more blocks to request.
				blist->last_sent=blk;
				continue;
			}
		}
		if(blk==blist->last_requested) break;
	}
	// Need to free stuff that is no longer needed.
	free_stuff(slist);
}
Beispiel #2
0
int restore_dir(struct asfd *asfd,
	struct sbuf *sb, const char *dname, enum action act, struct conf **confs)
{
	int ret=0;
	char *rpath=NULL;
	if(act==ACTION_RESTORE)
	{
		if(build_path(dname, "", &rpath, NULL))
		{
			ret=warn_and_interrupt(asfd, sb, confs,
				"build path failed: %s", dname);
			goto end;
		}
		else if(!is_dir_lstat(rpath))
		{
			if(mkdir(rpath, 0777))
			{
				ret=warn_and_interrupt(asfd, sb, confs,
					"mkdir error: %s", strerror(errno));
				goto end;
			}
		}
		attribs_set(asfd, rpath, &(sb->statp), sb->winattr, confs);
		if(!ret) cntr_add(get_cntr(confs[OPT_CNTR]), sb->path.cmd, 1);
	}
	else cntr_add(get_cntr(confs[OPT_CNTR]), sb->path.cmd, 1);
end:
	if(rpath) free(rpath);
	return ret;
}
Beispiel #3
0
static int restore_link(struct asfd *asfd, struct sbuf *sb,
	const char *fname, enum action act, struct conf **confs)
{
	int ret=0;

	if(act==ACTION_RESTORE)
	{
		char *rpath=NULL;
		if(build_path(fname, "", &rpath, NULL))
		{
			ret=warn_and_interrupt(asfd, sb, confs,
				"build path failed: %s", fname);
			goto end;
		}
		else if(make_link(asfd,
			fname, sb->link.buf, sb->link.cmd, confs))
		{
			ret=warn_and_interrupt(asfd, sb, confs,
				"could not create link", "");
			goto end;
		}
		else if(!ret)
		{
			attribs_set(asfd, fname,
				&(sb->statp), sb->winattr, confs);
			cntr_add(get_cntr(confs[OPT_CNTR]), sb->path.cmd, 1);
		}
		if(rpath) free(rpath);
	}
	else cntr_add(get_cntr(confs[OPT_CNTR]), sb->path.cmd, 1);
end:
	return ret;
}
Beispiel #4
0
int restore_sbuf_protocol1(struct asfd *asfd, struct sbuf *sb, struct bu *bu,
	enum action act, struct sdirs *sdirs,
	enum cntr_status cntr_status, struct conf **cconfs)
{
	if((sb->protocol1->datapth.buf
		&& asfd->write(asfd, &(sb->protocol1->datapth)))
	  || asfd->write(asfd, &sb->attr))
		return -1;
	else if(sbuf_is_filedata(sb)
	  || sbuf_is_vssdata(sb))
	{
		if(!sb->protocol1->datapth.buf)
		{
			logw(asfd, get_cntr(cconfs),
				"Got filedata entry with no datapth: %c:%s\n",
					sb->path.cmd, sb->path.buf);
			return 0;
		}
		return restore_file(asfd, bu, sb, act, sdirs, cconfs);
	}
	else
	{
		if(asfd->write(asfd, &sb->path))
			return -1;
		// If it is a link, send what
		// it points to.
		else if(sbuf_is_link(sb)
		  && asfd->write(asfd, &sb->link)) return -1;
		cntr_add(get_cntr(cconfs), sb->path.cmd, 0);
	}
	return 0;
}
Beispiel #5
0
static int deal_with_receive_end_file(struct asfd *asfd, struct sdirs *sdirs,
	struct sbuf *rb, struct fzp *chfp, struct conf **cconfs,
	char **last_requested)
{
	static char *cp=NULL;
	static struct iobuf *rbuf;
	rbuf=asfd->rbuf;
	// Finished the file.
	// Write it to the phase2 file, and free the buffers.

	if(fzp_close(&(rb->protocol1->fzp)))
	{
		logp("error closing delta for %s in receive\n", rb->path);
		goto error;
	}
	iobuf_move(&rb->protocol1->endfile, rbuf);
	if(rb->flags & SBUFL_RECV_DELTA && finish_delta(sdirs, rb))
		goto error;

	if(sbufl_to_manifest(rb, chfp))
		goto error;

	if(rb->flags & SBUFL_RECV_DELTA)
		cntr_add_changed(get_cntr(cconfs[OPT_CNTR]), rb->path.cmd);
	else
		cntr_add(get_cntr(cconfs[OPT_CNTR]), rb->path.cmd, 0);

	if(*last_requested && !strcmp(rb->path.buf, *last_requested))
	{
		free(*last_requested);
		*last_requested=NULL;
	}

	cp=strchr(rb->protocol1->endfile.buf, ':');
	if(rb->protocol1->endfile.buf)
		cntr_add_bytes(get_cntr(cconfs[OPT_CNTR]),
			strtoull(rb->protocol1->endfile.buf, NULL, 10));
	if(cp)
	{
		// checksum stuff goes here
	}

	sbuf_free_content(rb);
	return 0;
error:
	sbuf_free_content(rb);
	return -1;
}
Beispiel #6
0
static int restore_remaining_dirs(struct asfd *asfd, struct bu *bu,
	struct slist *slist, enum action act, struct sdirs *sdirs,
	enum cntr_status cntr_status, struct conf **cconfs)
{
	int ret=-1;
	struct sbuf *sb;
	struct sbuf *need_data=NULL;
	if(!(need_data=sbuf_alloc(get_protocol(cconfs)))) goto end;
	// Restore any directories that are left in the list.
	for(sb=slist->head; sb; sb=sb->next)
	{
		if(get_protocol(cconfs)==PROTO_1)
		{
			if(restore_sbuf_protocol1(asfd, sb, bu, act,
				sdirs, cntr_status, cconfs))
					goto end;
		}
		else
		{
			if(restore_sbuf_protocol2(asfd, sb, act,
				cntr_status, get_cntr(cconfs), need_data))
					goto end;
		}
	}
	ret=0;
end:
	sbuf_free(&need_data);
	return ret;
}
Beispiel #7
0
// return 1 to say that a file was processed
static int maybe_process_file(struct asfd *asfd,
	struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
	struct fzp *ucfp, struct conf **cconfs)
{
	switch(sbuf_pathcmp(cb, p1b))
	{
		case 0:
			return maybe_do_delta_stuff(asfd, sdirs, cb, p1b,
				ucfp, cconfs);
		case 1:
			//logp("ahead: %s\n", p1b->path);
			// ahead - need to get the whole file
			if(process_new(sdirs, cconfs, p1b, ucfp))
				return -1;
			// Do not free.
			return 1;
		case -1:
		default:
			//logp("behind: %s\n", p1b->path);
			// Behind - need to read more from the old manifest.
			// Count a deleted file - it was in the old manifest
			// but not the new.
			cntr_add_deleted(get_cntr(cconfs[OPT_CNTR]),
				cb->path.cmd);
			return 0;
	}
}
Beispiel #8
0
// Return -1 for error, 0 for could not open file, 1 for success.
int rabin_open_file(struct sbuf *sb, struct asfd *asfd, struct cntr *cntr,
                    struct conf **confs)
{
    struct BFILE *bfd=&sb->protocol2->bfd;
#ifdef HAVE_WIN32
    if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr))
#else
    if(lstat(sb->path.buf, &sb->statp))
#endif
    {
        // This file is no longer available.
        logw(asfd, cntr, "%s has vanished\n", sb->path.buf);
        return 0;
    }
    sb->compression=get_int(confs[OPT_COMPRESSION]);
    // Encryption not yet implemented in protocol2.
    //sb->protocol2->encryption=conf->protocol2->encryption_password?1:0;
    if(attribs_encode(sb)) return -1;
    if(sbuf_is_metadata(sb))
        return rabin_open_file_extrameta(sb, asfd, cntr);

    if(bfd->open_for_send(bfd, asfd,
                          sb->path.buf, sb->winattr,
                          get_int(confs[OPT_ATIME]), cntr, PROTO_2))
    {
        logw(asfd, get_cntr(confs),
             "Could not open %s\n", sb->path.buf);
        return 0;
    }
    return 1;
}
Beispiel #9
0
END_TEST

START_TEST(test_protocol1_restore_file_not_found)
{
	struct asfd *asfd;
	struct sbuf *sb;
	struct conf **confs;
	struct cntr *cntr;

	clean();

	confs=setup_confs();
	sb=setup_sbuf("/path", "/datapth", NULL, 0);

	asfd=asfd_mock_setup(&areads, &awrites);
	setup_not_found_message(asfd, sb);

	// Passing in NULL bu means that the file will not be found, as there
	// are no backups to traverse.
	// The function should return 0, so that the calling function
	// can continue.
	fail_unless(!restore_file(
		asfd,
		NULL /*bu*/,
		sb,
		ACTION_RESTORE,
		NULL /*sdirs*/,
		confs
	));
	cntr=get_cntr(confs);
	fail_unless(cntr->ent[CMD_WARNING]->count==1);
	tear_down(&sb, NULL, &confs, &asfd);
}
Beispiel #10
0
static int make_rev_sig(const char *dst, const char *sig, const char *endfile,
	int compression, struct conf **confs)
{
	int ret=-1;
	FILE *dstfp=NULL;
	gzFile dstzp=NULL;
	FILE *sigp=NULL;
//logp("make rev sig: %s %s\n", dst, sig);

	if(dpth_protocol1_is_compressed(compression, dst))
		dstzp=gzopen_file(dst, "rb");
	else
		dstfp=open_file(dst, "rb");

	if((!dstzp && !dstfp)
	  || !(sigp=open_file(sig, "wb"))
	  || rs_sig_gzfile(NULL, dstfp, dstzp, sigp,
		get_librsync_block_len(endfile),
		RS_DEFAULT_STRONG_LEN,
		NULL, get_cntr(confs[OPT_CNTR]))!=RS_DONE)
			goto end;
	ret=0;
end:
//logp("end of make rev sig\n");
	gzclose_fp(&dstzp);
	close_fp(&dstfp);
	if(close_fp(&sigp))
	{
		logp("error closing %s in %s\n", sig, __func__);
		return -1;
	}
	return ret;
}
Beispiel #11
0
// Used on resume, this just reads the phase1 file and sets up cntr.
static int read_phase1(struct manio *p1manio, struct conf **cconfs)
{
    int ret=-1;
    struct sbuf *p1b;
    enum protocol protocol=get_protocol(cconfs);
    struct cntr *cntr=get_cntr(cconfs);
    if(!(p1b=sbuf_alloc(protocol))) return -1;
    while(1)
    {
        sbuf_free_content(p1b);
        switch(manio_read(p1manio, p1b))
        {
        case 0:
            break;
        case 1:
            ret=0;
        default:
            goto end;
        }
        cntr_add_phase1(cntr, p1b->path.cmd, 0);

        if(sbuf_is_estimatable(p1b))
            cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
                         (uint64_t)p1b->statp.st_size);
    }
end:
    sbuf_free(&p1b);
    return ret;
}
Beispiel #12
0
Datei: main.c Projekt: scosu/burp
static enum cliret restore_wrapper(struct asfd *asfd, enum action action,
	int vss_restore, struct conf **confs)
{
	enum cliret ret=CLIENT_OK;
	const char *r_script_pre=get_string(confs[OPT_R_SCRIPT_PRE]);
	const char *r_script_post=get_string(confs[OPT_R_SCRIPT_POST]);

	if(r_script_pre)
	{
		int a=0;
		const char *args[12];
		args[a++]=r_script_pre;
		if(get_int(confs[OPT_R_SCRIPT_RESERVED_ARGS]))
		{
			args[a++]="pre";
			args[a++]="reserved2";
			args[a++]="reserved3";
			args[a++]="reserved4";
			args[a++]="reserved5";
		}
		args[a++]=NULL;
		if(run_script(asfd,
			args, get_strlist(confs[OPT_R_SCRIPT_PRE_ARG]),
			confs, 1, 1, 1))
				ret=CLIENT_ERROR;
	}
	if(ret==CLIENT_OK)
	{
		if(do_restore_client(asfd, confs,
			action, vss_restore)) ret=CLIENT_ERROR;
	}
	if((ret==CLIENT_OK || get_int(confs[OPT_R_SCRIPT_POST_RUN_ON_FAIL]))
	  && r_script_post)
	{
		int a=0;
		const char *args[12];
		args[a++]=r_script_pre;
		if(get_int(confs[OPT_R_SCRIPT_RESERVED_ARGS]))
		{
			args[a++]="post";
			// Tell post script whether the restore failed.
			args[a++]=ret?"1":"0";
			args[a++]="reserved3";
			args[a++]="reserved4";
			args[a++]="reserved5";
		}
		args[a++]=NULL;
		if(run_script(asfd,
			args, get_strlist(confs[OPT_R_SCRIPT_POST_ARG]),
			confs, 1, 1, 1))
				ret=CLIENT_ERROR;
	}

	// Return non-zero if there were warnings,
	// so that the test script can easily check.
	if(ret==CLIENT_OK && get_cntr(confs)->ent[CMD_WARNING]->count)
		ret=CLIENT_RESTORE_WARNINGS;

	return ret;
}
Beispiel #13
0
Datei: main.c Projekt: scosu/burp
static enum cliret initial_comms(struct async *as,
	enum action *action, char **incexc, struct conf **confs)
{
	struct asfd *asfd;
	char *server_version=NULL;
	enum cliret ret=CLIENT_OK;
	asfd=as->asfd;

	if(authorise_client(asfd, &server_version,
	  get_string(confs[OPT_CNAME]),
	  get_string(confs[OPT_PASSWORD]),
	  get_cntr(confs)))
		goto error;

	if(server_version)
	{
		logp("Server version: %s\n", server_version);
		// Servers before 1.3.2 did not tell us their versions.
		// 1.3.2 and above can do the automatic CA stuff that
		// follows.
		switch(ca_client_setup(asfd, confs))
		{
			case 0:
				break; // All OK.
			case 1:
				// Certificate signed successfully.
				// Everything is OK, but we will reconnect now,
				// in order to use the new keys/certificates.
				goto reconnect;
			default:
				logp("Error with cert signing request\n");
				goto error;
		}
	}

	set_non_blocking(asfd->fd);

	if(ssl_check_cert(asfd->ssl, NULL, confs))
	{
		logp("check cert failed\n");
		goto error;
	}

	if(extra_comms(as, confs, action, incexc))
	{
		logp("extra comms failed\n");
		goto error;
	}

	ret=CLIENT_OK; goto end;
error:
	ret=CLIENT_ERROR; goto end;
reconnect:
	ret=CLIENT_RECONNECT; goto end;
end:
	free_w(&server_version);
	return ret;
}
Beispiel #14
0
// FIX THIS: it only works with protocol1.
int restore_interrupt(struct asfd *asfd,
	struct sbuf *sb, const char *msg, struct conf **confs)
{
	int ret=0;
	struct cntr *cntr=get_cntr(confs[OPT_CNTR]);
	struct iobuf *rbuf=asfd->rbuf;

	if(get_e_protocol(confs[OPT_PROTOCOL])!=PROTO_1) return 0;
	if(!cntr) return 0;

	cntr_add(cntr, CMD_WARNING, 1);
	logp("WARNING: %s\n", msg);
	if(asfd->write_str(asfd, CMD_WARNING, msg)) goto end;

	// If it is file data, get the server
	// to interrupt the flow and move on.
	if(sb->path.cmd!=CMD_FILE
	  && sb->path.cmd!=CMD_ENC_FILE
	  && sb->path.cmd!=CMD_EFS_FILE
	  && sb->path.cmd!=CMD_VSS
	  && sb->path.cmd!=CMD_ENC_VSS
	  && sb->path.cmd!=CMD_VSS_T
	  && sb->path.cmd!=CMD_ENC_VSS_T)
		return 0;
	if(sb->protocol1 && !(sb->protocol1->datapth.buf))
		return 0;
	if(sb->protocol2 && !(sb->path.buf))
		return 0;

	if(asfd->write_str(asfd, CMD_INTERRUPT, sb->protocol1->datapth.buf))
		goto end;

	// Read to the end file marker.
	while(1)
	{
		iobuf_free_content(rbuf);
		if(asfd->read(asfd))
			goto end;
		if(!ret && rbuf->len)
		{
			if(rbuf->cmd==CMD_APPEND)
				continue;
			else if(rbuf->cmd==CMD_END_FILE)
				break;
			else
			{
				iobuf_log_unexpected(rbuf, __func__);
				goto end;
			}
		}
	}

	ret=0;
end:
	iobuf_free_content(rbuf);
	return ret;
}
Beispiel #15
0
static int run_list(struct asfd *asfd,
	struct sdirs *sdirs, struct conf **cconfs)
{
	int ret=-1;
	char *cp=NULL;
	char *backupno=NULL;
	char *browsedir=NULL;
	char *listregex=NULL;
	struct iobuf *rbuf=asfd->rbuf;

	if(!client_can_generic(cconfs, OPT_CLIENT_CAN_LIST))
	{
		logp("Not allowing list of %s\n",
			get_string(cconfs[OPT_CNAME]));
		asfd->write_str(asfd, CMD_GEN, "Client list is not allowed");
		goto end;
	}

	if(!strncmp_w(rbuf->buf, "list "))
	{
		if((cp=strchr(rbuf->buf, ':')))
		{
			*cp='\0';
			if(!(listregex=strdup_w(cp+1, __func__)))
				goto end;
		}
		if(!(backupno=strdup_w(rbuf->buf+strlen("list "), __func__)))
			goto end;
		
	}
	else if(!strncmp_w(rbuf->buf, "listb "))
	{
		if((cp=strchr(rbuf->buf, ':')))
		{
			*cp='\0';
			if(!(browsedir=strdup_w(cp+1, __func__)))
				goto end;
		}
		strip_trailing_slashes(&browsedir);
		if(!(backupno=strdup_w(rbuf->buf+strlen("listb "), __func__)))
			goto end;
	}
	if(asfd->write_str(asfd, CMD_GEN, "ok")) goto end;

	iobuf_free_content(asfd->rbuf);

	if(list_server_init(asfd, sdirs, get_cntr(cconfs),
		get_protocol(cconfs), backupno, listregex, browsedir))
			goto end;
	ret=do_list_server();
end:
	free_w(&backupno);
	free_w(&browsedir);
	free_w(&listregex);
	list_server_free();
	return ret;
}
Beispiel #16
0
static int changed_non_file(struct sbuf *p1b,
	struct manio *ucmanio, enum cmd cmd, struct conf **cconfs)
{
	// As new_non_file.
	if(manio_write_sbuf(ucmanio, p1b))
		return -1;
	cntr_add_changed(get_cntr(cconfs), cmd);
	sbuf_free_content(p1b);
	return 0;
}
Beispiel #17
0
static int actual_restore(struct asfd *asfd, struct bu *bu,
	const char *manifest, regex_t *regex, int srestore, enum action act,
	struct sdirs *sdirs, enum cntr_status cntr_status, struct conf **cconfs)
{
        int ret=-1;
	int do_restore_stream=1;
        // For out-of-sequence directory restoring so that the
        // timestamps come out right:
        struct slist *slist=NULL;

	if(linkhash_init()
          || !(slist=slist_alloc()))
                goto end;

	if(get_protocol(cconfs)==PROTO_2)
	{
		switch(maybe_restore_spool(asfd, manifest, sdirs, bu,
			srestore, regex, cconfs, slist, act, cntr_status))
		{
			case 1: do_restore_stream=0; break;
			case 0: do_restore_stream=1; break;
			default: goto end; // Error;
		}
	}
	if(do_restore_stream && restore_stream(asfd, sdirs, slist,
		bu, manifest, regex,
		srestore, cconfs, act, cntr_status))
			goto end;

	if(restore_remaining_dirs(asfd, bu, slist,
		act, sdirs, cntr_status, cconfs)) goto end;

        // Restore has nearly completed OK.

        ret=restore_end(asfd, cconfs);

	cntr_print(get_cntr(cconfs), act);
	cntr_stats_to_file(get_cntr(cconfs), bu->path, act, cconfs);
end:
        slist_free(&slist);
	linkhash_free();
        return ret;
}
Beispiel #18
0
static int process_unchanged_file(struct sbuf *p1b, struct sbuf *cb,
	struct fzp *ucfp, struct conf **cconfs)
{
	// Need to re-encode the p1b attribs to include compression and
	// other bits and pieces that are recorded on cb.
	iobuf_move(&p1b->protocol1->datapth, &cb->protocol1->datapth);
	iobuf_move(&p1b->protocol1->endfile, &cb->protocol1->endfile);
	p1b->compression=cb->compression;
	if(attribs_encode(p1b))
		return -1;
	if(sbufl_to_manifest(p1b, ucfp))
		return -1;
	cntr_add_same(get_cntr(cconfs[OPT_CNTR]), p1b->path.cmd);
	if(p1b->protocol1->endfile.buf) cntr_add_bytes(
		get_cntr(cconfs[OPT_CNTR]),
		 strtoull(p1b->protocol1->endfile.buf, NULL, 10));
	sbuf_free_content(cb);
	return 1;
}
Beispiel #19
0
static int make_rev_delta(const char *src, const char *sig, const char *del,
	int compression, struct conf **cconfs)
{
	int ret=-1;
	FILE *srcfp=NULL;
	FILE *delfp=NULL;
	FILE *sigp=NULL;
	gzFile srczp=NULL;
	gzFile delzp=NULL;
	rs_signature_t *sumset=NULL;

//logp("make rev delta: %s %s %s\n", src, sig, del);
	if(!(sigp=open_file(sig, "rb"))) goto end;

	if(rs_loadsig_file(sigp, &sumset, NULL)!=RS_DONE
	  || rs_build_hash_table(sumset)!=RS_DONE)
		goto end;

//logp("make rev deltb: %s %s %s\n", src, sig, del);

	if(dpth_protocol1_is_compressed(compression, src))
		srczp=gzopen_file(src, "rb");
	else
		srcfp=open_file(src, "rb");

	if(!srczp && !srcfp) goto end;

	if(get_int(cconfs[OPT_COMPRESSION]))
		delzp=gzopen_file(del, comp_level(cconfs));
	else
		delfp=open_file(del, "wb");
	if(!delzp && !delfp) goto end;

	if(rs_delta_gzfile(NULL, sumset, srcfp, srczp,
		delfp, delzp, NULL, get_cntr(cconfs[OPT_CNTR]))!=RS_DONE)
			goto end;
	ret=0;
end:
	if(sumset) rs_free_sumset(sumset);
	gzclose_fp(&srczp);
	close_fp(&srcfp);
	close_fp(&sigp);
	if(gzclose_fp(&delzp))
	{
		logp("error closing zp %s in %s\n", del, __func__);
		ret=-1;
	}
	if(close_fp(&delfp))
	{
		logp("error closing fp %s in %s\n", del, __func__);
		ret=-1;
	}
	return ret;
}
Beispiel #20
0
static int changed_non_file(struct sbuf *p1b,
	struct fzp *ucfp, enum cmd cmd, struct conf **cconfs)
{
	// As new_non_file.
	if(sbufl_to_manifest(p1b, ucfp))
		return -1;
	else
		cntr_add_changed(get_cntr(cconfs[OPT_CNTR]), cmd);
	sbuf_free_content(p1b);
	return 0;
}
Beispiel #21
0
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 **cconfs, struct sbuf *need_data, const char *manifest,
	struct slist *slist)
{
	//printf("%s: %s\n", act==ACTION_RESTORE?"restore":"verify", sb->path.buf);
	if(write_status(cntr_status, sb->path.buf, get_cntr(cconfs)))
		return -1;

	if(sb->path.cmd==CMD_HARD_LINK)
	{
		struct f_link *lp=NULL;
		struct f_link **bucket=NULL;
		if((lp=linkhash_search(&sb->statp, &bucket)))
		{
			// It is in the list of stuff that is in the manifest,
			// but was skipped on this restore.
			// Need to go through the manifest from the beginning,
			// and substitute in the data to restore to this
			// location.
			return hard_link_substitution(asfd, sb, lp,
				bu, act, sdirs,
				cntr_status, cconfs, manifest, slist);
			// FIX THIS: Would be nice to remember the new link
			// location so that further hard links would link to
			// it instead of doing the hard_link_substitution
			// business over again.
		}
	}

	if(get_protocol(cconfs)==PROTO_1)
	{
		return restore_sbuf_protocol1(asfd, sb, bu,
		  act, sdirs, cntr_status, cconfs);
	}
	else
	{
		return restore_sbuf_protocol2(asfd, sb,
		  act, cntr_status, get_cntr(cconfs), need_data);
	}
}
Beispiel #22
0
static int ft_err(struct asfd *asfd,
	struct conf **confs, struct FF_PKT *ff, const char *msg)
{
	int raise_error;
	const char *prefix="";
	raise_error=get_int(confs[OPT_SCAN_PROBLEM_RAISES_ERROR]);
	if(raise_error) prefix="Err: ";
	if(logw(asfd, get_cntr(confs), "%s%s %s: %s\n", prefix, msg,
		ff->fname, strerror(errno))) return -1;
	if(raise_error) return -1;
	return 0;
}
Beispiel #23
0
// FIX THIS: need to unit test this.
static int do_conf_switch_to_orig_client(struct conf **globalcs,
	struct conf **cconfs, const char *orig_client, const char *buf)
{
	int ret=-1;
	int loadrc;
	struct conf **sconfs=NULL;
	if(!(sconfs=confs_alloc())
	  || confs_init(sconfs)) goto end;
	if(set_string(sconfs[OPT_CNAME], orig_client))
		goto end;
	logp("Client wants to switch to client: %s\n",
		get_string(sconfs[OPT_CNAME]));

	// Allow unit testing using a buffer.
#ifdef UTEST
	if(buf) loadrc=conf_load_overrides_buf(globalcs, sconfs, buf);
	else
#endif
		loadrc=conf_load_clientconfdir(globalcs, sconfs);
	if(loadrc)
	{
		logp("Could not load alternate config: %s",
			get_string(sconfs[OPT_CNAME]));
		goto end;
	}
	set_int(sconfs[OPT_SEND_CLIENT_CNTR],
		get_int(cconfs[OPT_SEND_CLIENT_CNTR]));

	if(!restore_client_allowed(cconfs, sconfs))
		goto end;

	if(set_string(sconfs[OPT_RESTORE_PATH],
		get_string(cconfs[OPT_RESTORE_PATH])))
			goto end;
	if(set_string(cconfs[OPT_RESTORE_PATH], NULL))
		goto end;
	set_cntr(sconfs[OPT_CNTR], get_cntr(cconfs[OPT_CNTR]));
	set_cntr(cconfs[OPT_CNTR], NULL);
	confs_free_content(cconfs);
	confs_init(cconfs);
	confs_memcpy(cconfs, sconfs);
	confs_null(sconfs);
	if(set_string(cconfs[OPT_RESTORE_CLIENT],
		get_string(cconfs[OPT_CNAME]))) goto end;
	if(set_string(cconfs[OPT_ORIG_CLIENT],
		get_string(cconfs[OPT_CNAME]))) goto end;

	logp("Switched to client %s\n", get_string(cconfs[OPT_CNAME]));
	ret=0;
end:
	confs_free(&sconfs);
	return ret;
}
Beispiel #24
0
static int my_send_file(struct asfd *asfd, struct FF_PKT *ff, struct conf **confs)
{
	static struct sbuf *sb=NULL;
	struct cntr *cntr=get_cntr(confs);

	if(!sb && !(sb=sbuf_alloc(get_protocol(confs)))) return -1;

#ifdef HAVE_WIN32
	if(ff->winattr & FILE_ATTRIBUTE_ENCRYPTED)
	{
		if(ff->type==FT_REG
		  || ff->type==FT_DIR)
			return to_server(asfd, confs, ff, sb, CMD_EFS_FILE);
		return logw(asfd, cntr,
			"EFS type %d not yet supported: %s\n",
			ff->type, ff->fname);
	}
#endif

	switch(ff->type)
	{
		case FT_REG:
		case FT_RAW:
		case FT_FIFO:
			return do_to_server(asfd, confs, ff, sb, filesymbol,
				in_exclude_comp(get_strlist(confs[OPT_EXCOM]),
				  ff->fname, get_int(confs[OPT_COMPRESSION])));
		case FT_DIR:
		case FT_REPARSE:
		case FT_JUNCTION:
			return to_server(asfd, confs, ff, sb, dirsymbol);
		case FT_LNK_S:
			return to_server(asfd, confs, ff, sb, CMD_SOFT_LINK);
		case FT_LNK_H:
			return to_server(asfd, confs, ff, sb, CMD_HARD_LINK);
		case FT_SPEC:
			return to_server(asfd, confs, ff, sb, CMD_SPECIAL);
		case FT_NOFSCHG:
			return ft_err(asfd, confs, ff, "Will not descend: "
				"file system change not allowed");
		case FT_NOFOLLOW:
			return ft_err(asfd, confs, ff, "Could not follow link");
		case FT_NOSTAT:
			return ft_err(asfd, confs, ff, "Could not stat");
		case FT_NOOPEN:
			return ft_err(asfd, confs, ff, "Could not open directory");
		default:
			return logw(asfd, cntr,
				"Err: Unknown file type %d: %s\n",
				ff->type, ff->fname);
	}
}
Beispiel #25
0
static
#endif
int restore_file(struct asfd *asfd, struct bu *bu,
	struct sbuf *sb, enum action act,
	struct sdirs *sdirs, struct conf **cconfs)
{
	int ret=-1;
	char *path=NULL;
	struct bu *b;
	struct bu *hlwarn=NULL;
	struct stat statp;
	struct cntr *cntr=NULL;
	if(cconfs) cntr=get_cntr(cconfs);

	// Go up the array until we find the file in the data directory.
	for(b=bu; b; b=b->next)
	{
		free_w(&path);
		if(!(path=prepend_s(b->data, sb->protocol1->datapth.buf)))
			goto end;

		if(lstat(path, &statp) || !S_ISREG(statp.st_mode))
			continue;

		if(b!=bu && (bu->flags & BU_HARDLINKED)) hlwarn=b;

		if(process_data_dir_file(asfd, bu, b,
			path, sb, act, sdirs, cconfs))
				goto end;

		// This warning must be done after everything else,
		// Because the client does not expect another cmd after
		// the warning.
		if(hlwarn) logw(asfd, cntr, "restore found %s in %s\n",
			iobuf_to_printable(&sb->path),
			hlwarn->basename);
		ret=0; // All OK.
		break;
	}

	if(!b)
	{
		logw(asfd, cntr, "restore could not find %s (%s)\n",
			iobuf_to_printable(&sb->path),
			iobuf_to_printable(&sb->protocol1->datapth));
		ret=0; // Carry on to subsequent files.
	}
end:
	free_w(&path);
	return ret;
}
Beispiel #26
0
static int new_non_file(struct sbuf *p1b,
	struct manio *ucmanio, struct conf **cconfs)
{
	// Is something that does not need more data backed up.
	// Like a directory or a link or something like that.
	// Goes into the unchanged file, so that it does not end up out of
	// order with normal files, which has to wait around for their data
	// to turn up.
	if(manio_write_sbuf(ucmanio, p1b))
		return -1;
	cntr_add(get_cntr(cconfs), p1b->path.cmd, 0);
	sbuf_free_content(p1b);
	return 0;
}
Beispiel #27
0
static int add_to_blks_list(struct asfd *asfd, struct conf **confs,
	struct slist *slist)
{
	int just_opened=0;
	struct sbuf *sb=slist->last_requested;
	if(!sb) return 0;

	if(sb->protocol2->bfd.mode==BF_CLOSED)
	{
		char buf[32];
		struct cntr *cntr=NULL;
		if(confs) cntr=get_cntr(confs);
		switch(rabin_open_file(sb, asfd, cntr, confs))
		{
			case 1: // All OK.
				break;
			case 0: // Could not open file. Tell the server.
				base64_from_uint64(sb->protocol2->index, buf);
				if(asfd->write_str(asfd, CMD_INTERRUPT, buf))
					return -1;
				if(slist_del_sbuf(slist, sb))
					return -1;
				sbuf_free(&sb);
				return 0;
			default:
				return -1;
		}
		just_opened=1;
	}

	switch(blks_generate(sb, slist->blist, just_opened))
	{
		case 0: // All OK.
			break;
		case 1: // File ended.
			if(rabin_close_file(sb, asfd))
			{
				logp("Failed to close file %s\n",
					iobuf_to_printable(&sb->path));
				return -1;
			}
			slist->last_requested=sb->next;
			break;
		default:
			return -1;
	}

	return 0;
}
Beispiel #28
0
static int new_non_file(struct sbuf *p1b,
	struct fzp *ucfp, struct conf **cconfs)
{
	// Is something that does not need more data backed up.
	// Like a directory or a link or something like that.
	// Goes into the unchanged file, so that it does not end up out of
	// order with normal files, which has to wait around for their data
	// to turn up.
	if(sbufl_to_manifest(p1b, ucfp))
		return -1;
	else
		cntr_add(get_cntr(cconfs[OPT_CNTR]), p1b->path.cmd, 0);
	sbuf_free_content(p1b);
	return 0;
}
Beispiel #29
0
static int do_to_server(struct asfd *asfd,
	struct conf **confs, struct FF_PKT *ff, struct sbuf *sb,
	enum cmd cmd, int compression)
{
#ifdef HAVE_WIN32
	int split_vss=0;
	int strip_vss=0;
	if(get_protocol(confs)==PROTO_1)
	{
		split_vss=get_int(confs[OPT_SPLIT_VSS]);
		strip_vss=get_int(confs[OPT_STRIP_VSS]);
	}
#endif
	struct cntr *cntr=get_cntr(confs);
	sb->compression=compression;
	sb->encryption=encryption;
	sb->statp=ff->statp;
	attribs_encode(sb);

#ifdef HAVE_WIN32
	if(split_vss
	  && !strip_vss
	  && cmd!=CMD_EFS_FILE
	  && maybe_send_extrameta(asfd, ff->fname,
		cmd, sb, cntr, metasymbol))
			return -1;
#endif

	if(usual_stuff(asfd, cntr, ff->fname, ff->link, sb, cmd)) return -1;

	if(ff->type==FT_REG)
		cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
			(uint64_t)ff->statp.st_size);
#ifdef HAVE_WIN32
	if(split_vss
	  && !strip_vss
	  && cmd!=CMD_EFS_FILE
	// FIX THIS: May have to check that it is not a directory here.
	  && !S_ISDIR(sb->statp.st_mode) // does this work?
	  && maybe_send_extrameta(asfd,
		ff->fname, cmd, sb, cntr, vss_trail_symbol))
			return -1;
	return 0;
#else
	return maybe_send_extrameta(asfd, ff->fname, cmd, sb,
		cntr, metasymbol);
#endif
}
Beispiel #30
0
void version_warn(struct asfd *asfd, struct conf **confs, struct conf **cconfs)
{
	const char *cname=get_string(cconfs[OPT_CNAME]);
	const char *peer_version=get_string(cconfs[OPT_PEER_VERSION]);
	if(!peer_version || strcmp(peer_version, VERSION))
	{
		char msg[256]="";

		if(!peer_version || !*peer_version)
			snprintf(msg, sizeof(msg), "Client '%s' has an unknown version. Please upgrade.", cname?cname:"unknown");
		else
			snprintf(msg, sizeof(msg), "Client '%s' version '%s' does not match server version '%s'. An upgrade is recommended.", cname?cname:"unknown", peer_version, VERSION);
		if(confs) logw(asfd, get_cntr(confs), "%s\n", msg);
		logp("WARNING: %s\n", msg);
	}
}