Пример #1
0
// FIX THIS: Maybe should be in bfile.c.
enum ofr_e open_for_restore(struct asfd *asfd, BFILE *bfd, const char *path,
	struct sbuf *sb, int vss_restore, struct cntr *cntr,
	enum protocol protocol)
{
	static int flags;
        if(bfd->mode!=BF_CLOSED)
        {
#ifdef HAVE_WIN32
		if(bfd->path && !strcmp(bfd->path, path))
		{
			// Already open after restoring the VSS data.
			// Time now for the actual file data.
			return OFR_OK;
		}
		else
		{
#endif
			if(bfd->close(bfd, asfd))
			{
				logp("error closing %s in %s()\n",
					path, __func__);
				return OFR_ERROR;
			}
#ifdef HAVE_WIN32
		}
#endif
	}
	bfile_init(bfd, sb->winattr, cntr);
#ifdef HAVE_WIN32
	bfd->set_win32_api(bfd, vss_restore);
#endif
	if(S_ISDIR(sb->statp.st_mode))
	{
		// Windows directories are treated as having file data.
		flags=O_WRONLY|O_BINARY;
		mkdir(path, 0777);
	}
	else
		flags=O_WRONLY|O_BINARY|O_CREAT|O_TRUNC;

	if(bfd->open(bfd, asfd, path, flags, S_IRUSR | S_IWUSR))
	{
		berrno be;
		berrno_init(&be);
		char msg[256]="";
		snprintf(msg, sizeof(msg), "Could not open for writing %s: %s",
			path, berrno_bstrerror(&be, errno));
		if(restore_interrupt(asfd, sb, msg, cntr, protocol))
			return OFR_ERROR;
		return OFR_CONTINUE;
	}
	// Add attributes to bfd so that they can be set when it is closed.
	bfd->winattr=sb->winattr;
	memcpy(&bfd->statp, &sb->statp, sizeof(struct stat));
	return OFR_OK;
}
Пример #2
0
static int send_file(struct asfd *asfd, struct sbuf *sb,
	int patches, const char *best,
	uint64_t *bytes, struct cntr *cntr)
{
	int ret=0;
	static BFILE *bfd=NULL;

	if(!bfd && !(bfd=bfile_alloc())) return -1;

	bfile_init(bfd, 0, cntr);
	if(bfd->open_for_send(bfd, asfd, best, sb->winattr,
		1 /* no O_NOATIME */, cntr, PROTO_1)) return -1;
	//logp("sending: %s\n", best);
	if(asfd->write(asfd, &sb->path))
		ret=-1;
	else if(patches)
	{
		// If we did some patches, the resulting file
		// is not gzipped. Gzip it during the send. 
		ret=send_whole_file_gzl(asfd, best, sb->protocol1->datapth.buf,
			1, bytes, NULL, cntr, 9, bfd, NULL, 0);
	}
	else
	{
		// If it was encrypted, it may or may not have been compressed
		// before encryption. Send it as it as, and let the client
		// sort it out.
		if(sbuf_is_encrypted(sb))
		{
			ret=send_whole_filel(asfd, sb->path.cmd, best,
				sb->protocol1->datapth.buf, 1, bytes,
				cntr, bfd, NULL, 0);
		}
		// It might have been stored uncompressed. Gzip it during
		// the send. If the client knew what kind of file it would be
		// receiving, this step could disappear.
		else if(!dpth_protocol1_is_compressed(sb->compression,
			sb->protocol1->datapth.buf))
		{
			ret=send_whole_file_gzl(asfd,
				best, sb->protocol1->datapth.buf, 1, bytes,
				NULL, cntr, 9, bfd, NULL, 0);
		}
		else
		{
			// If we did not do some patches, the resulting
			// file might already be gzipped. Send it as it is.
			ret=send_whole_filel(asfd, sb->path.cmd, best,
				sb->protocol1->datapth.buf, 1, bytes,
				cntr, bfd, NULL, 0);
		}
	}
	bfd->close(bfd, asfd);
	return ret;
}
Пример #3
0
/* These receive_a_file() and send_file() functions are for use by extra_comms
   and the CA stuff, rather than backups/restores. */
int receive_a_file(struct asfd *asfd, const char *path, struct conf **confs)
{
	int ret=-1;
	BFILE *bfd=NULL;
	unsigned long long rcvdbytes=0;
	unsigned long long sentbytes=0;

	if(!(bfd=bfile_alloc())) goto end;
	bfile_init(bfd, 0, confs);
#ifdef HAVE_WIN32
	bfd->set_win32_api(bfd, 0);
#endif
	if(bfd->open(bfd, asfd, path,
		O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
		S_IRUSR | S_IWUSR))
	{
		berrno be;
		berrno_init(&be);
		logp("Could not open for writing %s: %s\n",
			path, berrno_bstrerror(&be, errno));
		goto end;
	}

	ret=transfer_gzfile_in(asfd, path, bfd, &rcvdbytes, &sentbytes, confs);
	if(bfd->close(bfd, asfd))
	{
		logp("error closing %s in receive_a_file\n", path);
		goto end;
	}
	logp("Received: %s\n", path);
	ret=0;
end:
	bfd->close(bfd, asfd);
	bfile_free(&bfd);
	return ret;
}
Пример #4
0
int do_restore_client(struct asfd *asfd,
	struct conf **confs, enum action act, int vss_restore)
{
	int ret=-1;
	char msg[512]="";
	struct sbuf *sb=NULL;
	struct blk *blk=NULL;
	BFILE *bfd=NULL;
	char *fullpath=NULL;
	char *style=NULL;
	char *datpath=NULL;
	struct cntr *cntr=get_cntr(confs);
	enum protocol protocol=get_protocol(confs);
	int strip=get_int(confs[OPT_STRIP]);
	int overwrite=get_int(confs[OPT_OVERWRITE]);
	const char *backup=get_string(confs[OPT_BACKUP]);
	const char *regex=get_string(confs[OPT_REGEX]);
	const char *restore_prefix=get_string(confs[OPT_RESTOREPREFIX]);
	const char *encryption_password=get_string(confs[OPT_ENCRYPTION_PASSWORD]);

	if(!(bfd=bfile_alloc())) goto end;

	bfile_init(bfd, 0, cntr);

	snprintf(msg, sizeof(msg), "%s %s:%s", act_str(act),
		backup?backup:"", regex?regex:"");
	logp("doing %s\n", msg);
	if(asfd->write_str(asfd, CMD_GEN, msg)
	  || asfd_read_expect(asfd, CMD_GEN, "ok"))
		goto error;
	logp("doing %s confirmed\n", act_str(act));

#if defined(HAVE_WIN32)
	if(act==ACTION_RESTORE) win32_enable_backup_privileges();
#endif

	if(!(style=get_restore_style(asfd, confs)))
		goto error;
	if(!strcmp(style, RESTORE_SPOOL))
	{
		if(restore_spool(asfd, confs, &datpath))
			goto error;
	}
	else
		logp("Streaming restore direct\n");

	logf("\n");

	if(get_int(confs[OPT_SEND_CLIENT_CNTR]) && cntr_recv(asfd, confs))
		goto error;

	if(!(sb=sbuf_alloc(protocol))
	  || (protocol==PROTO_2 && !(blk=blk_alloc())))
	{
		log_and_send_oom(asfd, __func__);
		goto error;
	}

	while(1)
	{
		sbuf_free_content(sb);
		if(protocol==PROTO_1)
			sb->flags |= SBUF_CLIENT_RESTORE_HACK;

		switch(sbuf_fill_from_net(sb, asfd, blk, datpath, cntr))
		{
			case 0: break;
			case 1: if(asfd->write_str(asfd, CMD_GEN,
				"restoreend ok")) goto error;
				goto end; // It was OK.
			default:
			case -1: goto error;
		}

		if(protocol==PROTO_2)
		{
			if(blk->data)
			{
				int wret=0;
				if(act==ACTION_VERIFY)
					cntr_add(cntr, CMD_DATA, 1);
				else
					wret=write_data(asfd, bfd, blk);
				if(!datpath) blk_free_content(blk);
				blk->data=NULL;
				if(wret) goto error;
				continue;
			}
			else if(sb->endfile.buf)
			{
				continue;
			}
		}

		switch(sb->path.cmd)
		{
			case CMD_DIRECTORY:
			case CMD_FILE:
			case CMD_ENC_FILE:
			case CMD_SOFT_LINK:
			case CMD_HARD_LINK:
			case CMD_SPECIAL:
			case CMD_METADATA:
			case CMD_ENC_METADATA:
			case CMD_VSS:
			case CMD_ENC_VSS:
			case CMD_VSS_T:
			case CMD_ENC_VSS_T:
			case CMD_EFS_FILE:
				if(strip)
				{
					int s;
					s=strip_path_components(asfd,
						sb, strip, cntr, protocol);
					if(s<0) goto error;
					if(s==0)
					{
						// Too many components stripped
						// - carry on.
						continue;
					}
					// It is OK, sb.path is now stripped.
				}
				free_w(&fullpath);
				if(!(fullpath=prepend_s(restore_prefix,
					sb->path.buf)))
				{
					log_and_send_oom(asfd, __func__);
					goto error;
				}
				if(act==ACTION_RESTORE)
				{
				  strip_invalid_characters(&fullpath);
				  if(!overwrite_ok(sb, overwrite,
#ifdef HAVE_WIN32
					bfd,
#endif
					fullpath))
				  {
					char msg[512]="";
					// Something exists at that path.
					snprintf(msg, sizeof(msg),
						"Path exists: %s\n", fullpath);
					if(restore_interrupt(asfd,
						sb, msg, cntr, protocol))
							goto error;
					continue;
				  }
				}
				break;
			case CMD_MESSAGE:
			case CMD_WARNING:
				log_recvd(&sb->path, cntr, 1);
				logf("\n");
				continue;
			default:
				break;
		}

		switch(sb->path.cmd)
		{
			// These are the same in both protocol1 and protocol2.
			case CMD_DIRECTORY:
				if(restore_dir(asfd, sb, fullpath, act, cntr,
					protocol))
						goto error;
				continue;
			case CMD_SOFT_LINK:
			case CMD_HARD_LINK:
				if(restore_link(asfd, sb, fullpath, act, cntr,
					protocol, restore_prefix))
						goto error;
				continue;
			case CMD_SPECIAL:
				if(restore_special(asfd, sb,
					fullpath, act, cntr, protocol))
						goto error;
				continue;
			default:
				break;
		}

		if(protocol==PROTO_2)
		{
			if(restore_switch_protocol2(asfd, sb, fullpath, act,
				bfd, vss_restore, cntr))
					goto error;
		}
		else
		{
			if(restore_switch_protocol1(asfd, sb, fullpath, act,
				bfd, vss_restore, cntr, encryption_password))
					goto error;
		}
	}

end:
	ret=0;
error:
	// It is possible for a fd to still be open.
	bfd->close(bfd, asfd);
	bfile_free(&bfd);

	cntr_print_end(cntr);
	cntr_print(cntr, act);

	if(!ret) logp("%s finished\n", act_str(act));
	else logp("ret: %d\n", ret);

	sbuf_free(&sb);
	free_w(&style);
	if(datpath)
	{
		recursive_delete(datpath);
		free_w(&datpath);
	}
	free_w(&fullpath);
	blk_free(&blk);

	return ret;
}
Пример #5
0
// FIX THIS: Maybe should be in bfile.c.
enum ofr_e open_for_restore(struct asfd *asfd, BFILE *bfd, const char *path,
	struct sbuf *sb, int vss_restore, struct cntr *cntr,
	enum protocol protocol)
{
	static int flags;
        if(bfd->mode!=BF_CLOSED)
        {
#ifdef HAVE_WIN32
		if(bfd->path && !strcmp(bfd->path, path))
		{
			// Already open after restoring the VSS data.
			// Time now for the actual file data.
			return OFR_OK;
		}
		else
		{
#endif
			if(bfd->close(bfd, asfd))
			{
				logp("error closing %s in %s()\n",
					path, __func__);
				return OFR_ERROR;
			}
#ifdef HAVE_WIN32
		}
#endif
	}

#ifdef HAVE_WIN32
	// Some massive hacks to work around times that winattr was not
	// getting set correctly inside server side backups.
	// The EFS one will stop burp segfaulting when restoring affected
	// EFS files.
	if(sb->path.cmd==CMD_EFS_FILE)
		sb->winattr |= FILE_ATTRIBUTE_ENCRYPTED;
	if(S_ISDIR(sb->statp.st_mode))
		sb->winattr |= FILE_ATTRIBUTE_DIRECTORY;
#endif

	bfile_init(bfd, sb->winattr, cntr);
#ifdef HAVE_WIN32
	bfd->set_win32_api(bfd, vss_restore);
#endif
	if(S_ISDIR(sb->statp.st_mode))
	{
		// Windows directories are treated as having file data.
		flags=O_WRONLY|O_BINARY;
		mkdir(path, 0777);
	}
	else
		flags=O_WRONLY|O_BINARY|O_CREAT|O_TRUNC;

	if(bfd->open(bfd, asfd, path, flags, S_IRUSR | S_IWUSR))
	{
		berrno be;
		berrno_init(&be);
		char msg[256]="";
		snprintf(msg, sizeof(msg), "Could not open for writing %s: %s",
			path, berrno_bstrerror(&be, errno));
		if(restore_interrupt(asfd, sb, msg, cntr, protocol))
			return OFR_ERROR;
		return OFR_CONTINUE;
	}
	// Add attributes to bfd so that they can be set when it is closed.
	bfd->winattr=sb->winattr;
	memcpy(&bfd->statp, &sb->statp, sizeof(struct stat));
	return OFR_OK;
}
Пример #6
0
static int do_send_file(struct asfd *asfd, struct sbuf *sb,
	int patches, const char *best, struct cntr *cntr)
{
	enum send_e ret=SEND_FATAL;
	struct BFILE bfd;
	uint64_t bytes=0; // Unused.

	bfile_init(&bfd, 0, cntr);
	if(bfd.open_for_send(&bfd, asfd, best, sb->winattr,
		1 /* no O_NOATIME */, cntr, PROTO_1))
			return SEND_FATAL;
	if(asfd->write(asfd, &sb->path))
		ret=SEND_FATAL;
	else if(patches)
	{
		// If we did some patches, the resulting file
		// is not gzipped. Gzip it during the send.
		ret=send_whole_file_gzl(
			asfd,
			sb->protocol1->datapth.buf,
			/*quick_read*/1,
			&bytes,
			/*encpassword*/NULL,
			cntr,
			/*compression*/9,
			&bfd,
			/*extrameta*/NULL,
			/*elen*/0,
			/*key_deriv*/ENCRYPTION_UNSET,
			/*salt*/0
		);
	}
	else
	{
		// If it was encrypted, it may or may not have been compressed
		// before encryption. Send it as it as, and let the client
		// sort it out.
		if(sbuf_is_encrypted(sb))
		{
			ret=send_whole_filel(asfd,
#ifdef HAVE_WIN32
				sb->path.cmd
#endif
				sb->protocol1->datapth.buf,
				1, &bytes, cntr, &bfd, NULL, 0);
		}
		// It might have been stored uncompressed. Gzip it during
		// the send. If the client knew what kind of file it would be
		// receiving, this step could disappear.
		else if(!dpth_protocol1_is_compressed(sb->compression,
			sb->protocol1->datapth.buf))
		{
			ret=send_whole_file_gzl(
				asfd,
				sb->protocol1->datapth.buf,
				/*quick_read*/1,
				&bytes,
				/*encpassword*/NULL,
				cntr,
				/*compression*/9,
				&bfd,
				/*extrameta*/NULL,
				/*elen*/0,
				/*key_deriv*/ENCRYPTION_UNSET,
				/*salt*/0
			);
		}
		else
		{
			// If we did not do some patches, the resulting
			// file might already be gzipped. Send it as it is.
			ret=send_whole_filel(asfd,
#ifdef HAVE_WIN32
				sb->path.cmd
#endif
				sb->protocol1->datapth.buf,
				1, &bytes, cntr, &bfd, NULL, 0);
		}
	}
	bfd.close(&bfd, asfd);

	switch(ret)
	{
		case SEND_OK:
		case SEND_ERROR: // Carry on.
			return 0;
		case SEND_FATAL:
		default:
			return -1;
	}
}