コード例 #1
0
ファイル: client.c プロジェクト: lolandkidtress/burp
// Return 0 for OK, -1 for error, 1 for timer conditions not met.
static int do_backup_client(struct config *conf, int resume, int estimate, struct cntr *p1cntr, struct cntr *cntr)
{
	int ret=0;

	if(estimate)
		logp("do estimate client\n");
	else
		logp("do backup client\n");

#if defined(HAVE_WIN32)
	win32_enable_backup_privileges();
#endif
#if defined(WIN32_VSS)
	if((ret=win32_start_vss(conf))) return ret;
#endif

	// Scan the file system and send the results to the server.
	// Skip phase1 if the server wanted to resume.
	if(!ret && !resume) ret=backup_phase1_client(conf,
		estimate, p1cntr, cntr);

	// Now, the server will be telling us what data we need to send.
	if(!estimate && !ret)
		ret=backup_phase2_client(conf, p1cntr, resume, cntr);

	if(estimate)
		print_filecounters(p1cntr, cntr, ACTION_ESTIMATE);

#if defined(WIN32_VSS)
	win32_stop_vss();
#endif

	return ret;
}
コード例 #2
0
ファイル: backup_phase2_client.c プロジェクト: barroque/burp
int backup_phase2_client(struct config *conf, struct cntr *p1cntr, int resume, struct cntr *cntr)
{
	int ret=0;

	logp("Phase 2 begin (send file data)\n");

	ret=do_backup_phase2_client(conf, resume, p1cntr, cntr);

	print_endcounter(cntr);
	print_filecounters(p1cntr, cntr, ACTION_BACKUP);

	if(ret) logp("Error in phase 2\n");
	logp("Phase 2 end (send file data)\n");

	return ret;
}
コード例 #3
0
ファイル: restore_server.c プロジェクト: barroque/burp
// a = length of struct bu array
// i = position to restore from
static int restore_manifest(struct bu *arr, int a, int i, const char *tmppath1, const char *tmppath2, regex_t *regex, int srestore, enum action act, const char *client, char **dir_for_notify, struct cntr *p1cntr, struct cntr *cntr, struct config *cconf)
{
	int ret=0;
	gzFile zp=NULL;
	char *manifest=NULL;
	char *datadir=NULL;
	FILE *logfp=NULL;
	char *logpath=NULL;
	char *logpathz=NULL;
	// For sending status information up to the server.
	char status=STATUS_RESTORING;

	if(act==ACTION_RESTORE) status=STATUS_RESTORING;
	else if(act==ACTION_VERIFY) status=STATUS_VERIFYING;

	if(
	    (act==ACTION_RESTORE && !(logpath=prepend_s(arr[i].path, "restorelog", strlen("restorelog"))))
	 || (act==ACTION_RESTORE && !(logpathz=prepend_s(arr[i].path, "restorelog.gz", strlen("restorelog.gz"))))
	 || (act==ACTION_VERIFY && !(logpath=prepend_s(arr[i].path, "verifylog", strlen("verifylog"))))
	 || (act==ACTION_VERIFY && !(logpathz=prepend_s(arr[i].path, "verifylog.gz", strlen("verifylog.gz"))))
	 || !(manifest=prepend_s(arr[i].path, "manifest.gz", strlen("manifest.gz"))))
	{
		log_and_send_oom(__FUNCTION__);
		ret=-1;
	}
	else if(!(logfp=open_file(logpath, "ab")) || set_logfp(logfp, cconf))
	{
		char msg[256]="";
		snprintf(msg, sizeof(msg),
			"could not open log file: %s", logpath);
		log_and_send(msg);
		ret=-1;
	}

	*dir_for_notify=strdup(arr[i].path);

	log_restore_settings(cconf, srestore);

	// First, do a pass through the manifest to set up the counters.
	// This is the equivalent of a phase1 scan during backup.
	if(!ret && !(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send("could not open manifest");
		ret=-1;
	}
	else
	{
		int ars=0;
		int quit=0;
		struct sbuf sb;
		init_sbuf(&sb);
		while(!quit)
		{
			if((ars=sbuf_fill(NULL, zp, &sb, cntr)))
			{
				if(ars<0) ret=-1;
				// ars==1 means end ok
				quit++;
			}
			else
			{
				if((!srestore
				    || check_srestore(cconf, sb.path))
				  && check_regex(regex, sb.path))
				{
					do_filecounter(p1cntr, sb.cmd, 0);
					if(sb.endfile)
					  do_filecounter_bytes(p1cntr,
                 			    strtoull(sb.endfile, NULL, 10));
/*
					if(sb.cmd==CMD_FILE
					  || sb.cmd==CMD_ENC_FILE
					  || sb.cmd==CMD_METADATA
					  || sb.cmd==CMD_ENC_METADATA
					  || sb.cmd==CMD_VSS
					  || sb.cmd==CMD_ENC_VSS
					  || sb.cmd==CMD_VSS_T
					  || sb.cmd==CMD_ENC_VSS_T
					  || sb.cmd==CMD_EFS_FILE)
						do_filecounter_bytes(p1cntr,
							(unsigned long long)
							sb.statp.st_size);
*/
				}
			}
			free_sbuf(&sb);
		}
		free_sbuf(&sb);
		gzclose_fp(&zp);
	}

	if(cconf->send_client_counters)
	{
		if(send_counters(client, p1cntr, cntr))
		{
			ret=-1;
		}
	}

	// Now, do the actual restore.
	if(!ret && !(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send("could not open manifest");
		ret=-1;
	}
	else
	{
		char cmd;
		int s=0;
		int quit=0;
		size_t len=0;
		struct sbuf sb;
		// For out-of-sequence directory restoring so that the
		// timestamps come out right:
		int scount=0;
		struct sbuf **sblist=NULL;

		init_sbuf(&sb);

		while(!quit)
		{
			int ars=0;
			char *buf=NULL;
			if(async_read_quick(&cmd, &buf, &len))
			{
				logp("read quick error\n");
				ret=-1; quit++; break;
			}
			if(buf)
			{
				//logp("got read quick\n");
				if(cmd==CMD_WARNING)
				{
					logp("WARNING: %s\n", buf);
					do_filecounter(cntr, cmd, 0);
					free(buf); buf=NULL;
					continue;
				}
				else if(cmd==CMD_INTERRUPT)
				{
					// Client wanted to interrupt the
					// sending of a file. But if we are
					// here, we have already moved on.
					// Ignore.
					free(buf); buf=NULL;
					continue;
				}
				else
				{
					logp("unexpected cmd from client: %c:%s\n", cmd, buf);
					free(buf); buf=NULL;
					ret=-1; quit++; break;
				}
			}

			if((ars=sbuf_fill(NULL, zp, &sb, cntr)))
			{
				if(ars<0) ret=-1;
				// ars==1 means end ok
				quit++;
			}
			else
			{
				if((!srestore
				    || check_srestore(cconf, sb.path))
				  && check_regex(regex, sb.path)
				  && restore_ent(client,
					&sb, &sblist, &scount,
					arr, a, i, tmppath1, tmppath2,
					act, status, cconf,
					cntr, p1cntr))
				{
					ret=-1;
					quit++;
				}
			}
			free_sbuf(&sb);
		}
		gzclose_fp(&zp);
		// Restore any directories that are left in the list.
		if(!ret) for(s=scount-1; s>=0; s--)
		{
			if(restore_sbuf(sblist[s], arr, a, i,
				tmppath1, tmppath2, act, client, status,
				p1cntr, cntr, cconf))
			{
				ret=-1;
				break;
			}
		}
		free_sbufs(sblist, scount);

		if(!ret) ret=do_restore_end(act, cntr);

		//print_endcounter(cntr);
		print_filecounters(p1cntr, cntr, act);

		reset_filecounter(p1cntr, time(NULL));
		reset_filecounter(cntr, time(NULL));
	}
	set_logfp(NULL, cconf);
	compress_file(logpath, logpathz, cconf);
	if(manifest) free(manifest);
	if(datadir) free(datadir);
	if(logpath) free(logpath);
	if(logpathz) free(logpathz);
	return ret;
}
コード例 #4
0
ファイル: restore_server.c プロジェクト: fenio/burp
// a = length of struct bu array
// i = position to restore from
static int restore_manifest(struct bu *arr, int a, int i, const char *tmppath1, const char *tmppath2, regex_t *regex, enum action act, const char *client, struct cntr *p1cntr, struct cntr *cntr, struct config *cconf, bool all)
{
	int ret=0;
	gzFile zp=NULL;
	char *manifest=NULL;
	char *datadir=NULL;
	FILE *logfp=NULL;
	char *logpath=NULL;
	char *logpathz=NULL;
	// For sending status information up to the server.
	char status=STATUS_RESTORING;

	if(act==ACTION_RESTORE) status=STATUS_RESTORING;
	else if(act==ACTION_VERIFY) status=STATUS_VERIFYING;

	if(
	    (act==ACTION_RESTORE && !(logpath=prepend_s(arr[i].path, "restorelog", strlen("restorelog"))))
	 || (act==ACTION_RESTORE && !(logpathz=prepend_s(arr[i].path, "restorelog.gz", strlen("restorelog.gz"))))
	 || (act==ACTION_VERIFY && !(logpath=prepend_s(arr[i].path, "verifylog", strlen("verifylog"))))
	 || (act==ACTION_VERIFY && !(logpathz=prepend_s(arr[i].path, "verifylog.gz", strlen("verifylog.gz"))))
	 || !(manifest=prepend_s(arr[i].path, "manifest.gz", strlen("manifest.gz"))))
	{
		log_and_send("out of memory");
		ret=-1;
	}
	else if(!(logfp=open_file(logpath, "ab")) || set_logfp(logfp))
	{
		char msg[256]="";
		snprintf(msg, sizeof(msg),
			"could not open log file: %s", logpath);
		log_and_send(msg);
		ret=-1;
	}
	else if(!(zp=gzopen_file(manifest, "rb")))
	{
		log_and_send("could not open manifest");
		ret=-1;
	}
	else
	{
		char cmd;
		int quit=0;
		size_t len=0;
		struct sbuf sb;
		// For out-of-sequence directory restoring so that the
		// timestamps come out right:
		int s=0;
		int scount=0;
		struct sbuf **sblist=NULL;

		init_sbuf(&sb);

		while(!quit)
		{
			int ars=0;
			char *buf=NULL;
			if(async_read_quick(&cmd, &buf, &len))
			{
				logp("read quick error\n");
				ret=-1; quit++; break;
			}
			if(buf)
			{
				//logp("got read quick\n");
				if(cmd==CMD_WARNING)
				{
					logp("WARNING: %s\n", buf);
					do_filecounter(cntr, cmd, 0);
					free(buf); buf=NULL;
					continue;
				}
				else if(cmd==CMD_INTERRUPT)
				{
					// Client wanted to interrupt the
					// sending of a file. But if we are
					// here, we have already moved on.
					// Ignore.
					free(buf); buf=NULL;
					continue;
				}
				else
				{
					logp("unexpected cmd from client: %c:%s\n", cmd, buf);
					free(buf); buf=NULL;
					ret=-1; quit++; break;
				}
			}

			if((ars=sbuf_fill(NULL, zp, &sb, cntr)))
			{
				if(ars<0) ret=-1;
				// ars==1 means end ok
				quit++;
			}
			else
			{
				if(check_regex(regex, sb.path))
				{
				  // Check if we have any directories waiting
				  // to be restored.
				  for(s=scount-1; s>=0; s--)
				  {
					if(is_subdir(sblist[s]->path, sb.path))
					{
						// We are still in a subdir.
						//printf(" subdir (%s %s)\n", sblist[s]->path, sb.path);
						break;
					}
					else
					{
						// Can now restore sblist[s]
						// because nothing else is
						// fiddling in a subdirectory.
				  		if(restore_sbuf(sblist[s], arr,
						 a, i, tmppath1, tmppath2, act,
						 client, status,
						 p1cntr, cntr, cconf))
						{
							ret=-1; quit++;
							break;
						}
						else if(del_from_sbuf_arr(
							&sblist, &scount))
						{
							ret=-1; quit++;
							break;
						}
					}
				  }

				  /* If it is a directory, need to remember it
				     and restore it later, so that the
				     permissions come out right. */
				  /* Meta data of directories will also have
				     the stat stuff set to be a directory,
				     so will also come out at the end. */
				  if(!ret && S_ISDIR(sb.statp.st_mode))
				  {
					if(add_to_sbuf_arr(&sblist, &sb, &scount))
					{
						ret=-1; quit++;
					}

					// Wipe out sb, without freeing up
					// all the strings inside it, which
					// have been added to sblist.
					init_sbuf(&sb);
				  }
				  else if(!ret && restore_sbuf(&sb, arr, a, i,
				    tmppath1, tmppath2, act, client, status,
				    p1cntr, cntr, cconf))
				  {
					ret=-1; quit++;
				  }
				}
			}
			free_sbuf(&sb);
		}
		gzclose_fp(&zp);
		// Restore any directories that are left in the list.
		if(!ret) for(s=scount-1; s>=0; s--)
		{
			if(restore_sbuf(sblist[s], arr, a, i,
				tmppath1, tmppath2, act, client, status,
				p1cntr, cntr, cconf))
			{
				ret=-1;
				break;
			}
		}
		free_sbufs(sblist, scount);

		if(!ret && !all) ret=do_restore_end(act, cntr);

		print_endcounter(cntr);
		print_filecounters(p1cntr, cntr, act, 0);

		reset_filecounter(p1cntr);
		reset_filecounter(cntr);
	}
	set_logfp(NULL);
	compress_file(logpath, logpathz, cconf);
	if(manifest) free(manifest);
	if(datadir) free(datadir);
	if(logpath) free(logpath);
	if(logpathz) free(logpathz);
	return ret;
}
コード例 #5
0
ファイル: backup_phase4_server.c プロジェクト: tcheneau/burp
int backup_phase4_server(const char *basedir, const char *working, const char *current, const char *currentdata, const char *finishing, struct config *cconf, const char *client, struct cntr *p1cntr, struct cntr *cntr)
{
	int ret=0;
	struct stat statp;
	char *manifest=NULL;
	char *datadir=NULL;
	char *datadirtmp=NULL;
	char *currentdup=NULL;
	char *currentduptmp=NULL;
	char *currentdupdata=NULL;
	char *forward=NULL;
	char *timestamp=NULL;
	char *fullrealcurrent=NULL;
	char *deleteme=NULL;
	char *logpath=NULL;
	char *hlinkedpath=NULL;
	int len=0;
	char realcurrent[256]="";
	FILE *logfp=NULL;

	if((len=readlink(current, realcurrent, sizeof(realcurrent)-1))<0)
		len=0;
	realcurrent[len]='\0';

	if(!(datadir=prepend_s(finishing, "data", strlen("data")))
	  || !(datadirtmp=prepend_s(finishing, "data.tmp", strlen("data.tmp")))
	  || !(manifest=prepend_s(finishing, "manifest.gz", strlen("manifest.gz")))
	  || !(currentdup=prepend_s(finishing, "currentdup", strlen("currentdup")))
	  || !(currentduptmp=prepend_s(finishing, "currentdup.tmp", strlen("currentdup.tmp")))
	  || !(currentdupdata=prepend_s(currentdup, "data", strlen("data")))
	  || !(forward=prepend_s(currentdup, "forward", strlen("forward")))
	  || !(timestamp=prepend_s(finishing, "timestamp", strlen("timestamp")))
	  || !(fullrealcurrent=prepend_s(basedir, realcurrent, strlen(realcurrent)))
	  || !(deleteme=prepend_s(basedir, "deleteme", strlen("deleteme")))
	  || !(logpath=prepend_s(finishing, "log", strlen("log")))
	  || !(hlinkedpath=prepend_s(currentdup, "hardlinked", strlen("hardlinked"))))
	{
		ret=-1;
		goto endfunc;
	}

	if(!(logfp=open_file(logpath, "ab")) || set_logfp(logfp, cconf))
	{
		ret=-1;
		goto endfunc;
	}

	logp("Begin phase4 (shuffle files)\n");

	write_status(client, STATUS_SHUFFLING, NULL, p1cntr, cntr);

	if(!lstat(current, &statp)) // Had a previous backup
	{
		unsigned long bno=0;
		FILE *fwd=NULL;
		int hardlinked=0;
		char tstmp[64]="";
		int newdup=0;

		if(lstat(currentdup, &statp))
		{
			// Have not duplicated the current backup yet.
			if(!lstat(currentduptmp, &statp))
			{
				logp("Removing previous currentduptmp directory: %s\n", currentduptmp);
				if(recursive_delete(currentduptmp,
					NULL, TRUE /* del files */))
				{
					logp("Could not delete %s\n",
						currentduptmp);
					ret=-1;
					goto endfunc;
				}
			}
			logp("Duplicating current backup.\n");
			if(recursive_hardlink(current, currentduptmp, client,
				p1cntr, cntr, cconf)
			  || do_rename(currentduptmp, currentdup))
			{
				ret=-1;
				goto endfunc;
			}
			newdup++;
		}

		if(read_timestamp(timestamp, tstmp, sizeof(tstmp)))
		{
			logp("could not read timestamp file: %s\n", timestamp);
			ret=-1;
			goto endfunc;
		}
		// Get the backup number.
		bno=strtoul(tstmp, NULL, 10);

		// Put forward reference in, indicating the timestamp of
		// the working directory (which will soon become the current
		// directory).
		if(!(fwd=open_file(forward, "wb")))
		{
			log_and_send("could not create forward file");
			ret=-1;
			goto endfunc;
		}
		fprintf(fwd, "%s\n", tstmp);
		close_fp(&fwd);

		if(newdup)
		{
			// When we have just created currentdup, determine
			// hardlinked archive from the conf and the backup
			// number...
			hardlinked=do_hardlinked_archive(cconf, bno);
		}
		else
		{
			// ...if recovering, find out what currentdup started
			// out as.
			// Otherwise it is possible that things can be messed
			// up by somebody swapping between hardlinked and
			// not hardlinked at the same time as a resume happens.
			if(lstat(hlinkedpath, &statp))
			{
				logp("previous attempt started not hardlinked\n");
				hardlinked=0;
			}
			else
			{
				logp("previous attempt started hardlinked\n");
				hardlinked=1;
			}
		}

		if(hardlinked)
		{
			// Create a file to indicate that the previous backup
			// does not have others depending on it.
			FILE *hfp=NULL;
			if(!(hfp=open_file(hlinkedpath, "wb")))
			{
				ret=-1;
				goto endfunc;
			}
			// Stick the next backup timestamp in it. It might
			// be useful one day when wondering when the next
			// backup, now deleted, was made.
			fprintf(hfp, "%s\n", tstmp);
			close_fp(&hfp);
			logp(" doing hardlinked archive\n");
			logp(" will not generate reverse deltas\n");
		}
		else
		{
			logp(" not doing hardlinked archive\n");
			logp(" will generate reverse deltas\n");
			unlink(hlinkedpath);
		}

		if(atomic_data_jiggle(finishing,
			working, manifest, currentdup,
			currentdupdata,
			datadir, datadirtmp, cconf, client,
			hardlinked, bno, p1cntr, cntr))
		{
			logp("could not finish up backup.\n");
			ret=-1;
			goto endfunc;
		}

		write_status(client, STATUS_SHUFFLING,
			"deleting temporary files", p1cntr, cntr);

		// Remove the temporary data directory, we have now removed
		// everything useful from it.
		recursive_delete(datadirtmp, NULL, TRUE /* del files */);

		// Clean up the currentdata directory - this is now the 'old'
		// currentdata directory. Any files that were deleted from
		// the client will be left in there, so call recursive_delete
		// with the option that makes it not delete files.
		// This will have the effect of getting rid of unnecessary
		// directories.
		sync(); // try to help CIFS
		recursive_delete(currentdupdata, NULL, FALSE /* do not del files */);

		// Rename the old current to something that we know to
		// delete.
		if(do_rename(fullrealcurrent, deleteme))
		{
			ret=-1;
			goto endfunc;
		}
	}
	else
	{
		// No previous backup, just put datadirtmp in the right place.
		if(do_rename(datadirtmp, datadir))
		{
			ret=-1;
			goto endfunc;
		}
	}

	if(!lstat(deleteme, &statp))
	{
		// Rename the currentdup directory...
		// IMPORTANT TODO: read the path to fullrealcurrent
		// from the deleteme timestamp.
		do_rename(currentdup, fullrealcurrent);

		recursive_delete(deleteme, NULL, TRUE /* delete all */);
	}

	// Rename the finishing symlink so that it becomes the current symlink
	do_rename(finishing, current);

	print_filecounters(p1cntr, cntr, ACTION_BACKUP, 0);
	logp("Backup completed.\n");
	logp("End phase4 (shuffle files)\n");
	set_logfp(NULL, cconf); // will close logfp.

	compress_filename(current, "log", "log.gz", cconf);

endfunc:
	if(datadir) free(datadir);
	if(datadirtmp) free(datadirtmp);
	if(manifest) free(manifest);
	if(currentdup) free(currentdup);
	if(currentduptmp) free(currentduptmp);
	if(currentdupdata) free(currentdupdata);
	if(forward) free(forward);
	if(timestamp) free(timestamp);
	if(fullrealcurrent) free(fullrealcurrent);
	if(deleteme) free(deleteme);
	if(logpath) free(logpath);
	if(hlinkedpath) free(hlinkedpath);

	return ret;
}