示例#1
0
static int parse_client_data(struct asfd *srfd,
	struct cstat *clist, struct conf **confs)
{
	int ret=0;
	char *command=NULL;
	char *client=NULL;
	char *backup=NULL;
	char *logfile=NULL;
	char *browse=NULL;
	const char *cp=NULL;
	struct cstat *cstat=NULL;
        struct bu *bu=NULL;
//printf("got client data: '%s'\n", srfd->rbuf->buf);

	cp=srfd->rbuf->buf;

	// The client monitor will send an initial blank line to kick things
	// off. Until it is sent, we will not even have entered the code
	// in this file. So, without it, data from the parent will not have
	// been read, and the monitor client will be given incomplete
	// information for its first response.
	// Just ignore the new line at this point, it has served its purpose.
	if(srfd->rbuf->len==1
	  && !strcmp(cp, "\n"))
	{
		ret=0;
		goto end;
	}
	command=get_str(&cp, "j:", 0);
	client=get_str(&cp, "c:", 0);
	backup=get_str(&cp, "b:", 0);
	logfile=get_str(&cp, "l:", 0);
	browse=get_str(&cp, "p:", 1);

	if(command)
	{
		if(!strcmp(command, "pretty-print-on"))
		{
			json_set_pretty_print(1);
			if(json_send_warn(srfd, "Pretty print on"))
				goto error;
		}
		else if(!strcmp(command, "pretty-print-off"))
		{
			json_set_pretty_print(0);
			if(json_send_warn(srfd, "Pretty print off"))
				goto error;
		}
		else
		{
			if(json_send_warn(srfd, "Unknown command"))
				goto error;
		}
		goto end;
	}

	if(browse)
	{
		free_w(&logfile);
		if(!(logfile=strdup_w("manifest", __func__)))
			goto error;
		strip_trailing_slashes(&browse);
	}

//dump_cbno(clist, "pcd");

	if(client && *client)
	{
		if(!(cstat=cstat_get_by_name(clist, client)))
		{
			if(json_send_warn(srfd, "Could not find client"))
				goto error;
			goto end;
		}

		if(cstat_set_backup_list(cstat))
		{
			if(json_send_warn(srfd, "Could not get backup list"))
				goto error;
			goto end;
			
		}
	}
	if(cstat && backup)
	{
		unsigned long bno=0;
		if(!(bno=strtoul(backup, NULL, 10)))
		{
			if(json_send_warn(srfd, "Could not get backup number"))
				goto error;
			goto end;
		}
		for(bu=cstat->bu; bu; bu=bu->prev)
			if(bu->bno==bno) break;

		if(!bu)
		{
			if(json_send_warn(srfd, "Backup not found"))
				goto error;
			goto end;
		}
	}
	if(logfile)
	{
		if(strcmp(logfile, "manifest")
		  && strcmp(logfile, "backup")
		  && strcmp(logfile, "restore")
		  && strcmp(logfile, "verify")
		  && strcmp(logfile, "backup_stats")
		  && strcmp(logfile, "restore_stats")
		  && strcmp(logfile, "verify_stats"))
		{
			if(json_send_warn(srfd, "File not supported"))
				goto error;
			goto end;
		}
	}
/*
	printf("client: %s\n", client?:"");
	printf("backup: %s\n", backup?:"");
	printf("logfile: %s\n", logfile?:"");
*/

	if(cstat)
	{
		if(!cstat->run_status)
			cstat_set_run_status(cstat);
	}
	else for(cstat=clist; cstat; cstat=cstat->next)
	{
		if(!cstat->run_status)
			cstat_set_run_status(cstat);
	}

	if(json_send(srfd, clist, cstat, bu, logfile, browse,
		get_int(confs[OPT_MONITOR_BROWSE_CACHE])))
			goto error;

	goto end;
error:
	ret=-1;
end:
	free_w(&client);
	free_w(&backup);
	free_w(&logfile);
	free_w(&browse);
	return ret;
}
示例#2
0
static int do_recursive_delete(const char *d, const char *file, uint8_t delfiles, int32_t name_max)
{
	int ret=RECDEL_ERROR;
	DIR *dirp=NULL;
	struct dirent *entry=NULL;
	struct dirent *result;
	struct stat statp;
	char *directory=NULL;
	char *fullpath=NULL;

	if(!file)
	{
		if(!(directory=prepend_s(d, ""))) goto end;
	}
	else if(!(directory=prepend_s(d, file)))
	{
		log_out_of_memory(__func__);
		goto end;
	}

	if(lstat(directory, &statp))
	{
		// path does not exist.
		ret=RECDEL_OK;
		goto end;
	}

	if(!(dirp=opendir(directory)))
	{
		logp("opendir %s: %s\n", directory, strerror(errno));
		goto end;
	}

	if(!(entry=(struct dirent *)
		malloc_w(sizeof(struct dirent)+name_max+100, __func__)))
			goto end;

	while(1)
	{
		if(readdir_r(dirp, entry, &result) || !result)
		{
			// Got to the end of the directory.
			ret=RECDEL_OK;
			break;
		}

		if(entry->d_ino==0
		  || !strcmp(entry->d_name, ".")
		  || !strcmp(entry->d_name, ".."))
			continue;
		free_w(&fullpath);
		if(!(fullpath=prepend_s(directory, entry->d_name)))
			goto end;

		if(is_dir(fullpath, entry))
		{
			int r;
			if((r=do_recursive_delete(directory, entry->d_name,
				delfiles, name_max))==RECDEL_ERROR)
					goto end;
			// do not overwrite ret with OK if it previously
			// had ENTRIES_REMAINING
			if(r==RECDEL_ENTRIES_REMAINING) ret=r;
		}
		else if(delfiles)
		{
			if(unlink(fullpath))
			{
				logp("unlink %s: %s\n",
					fullpath, strerror(errno));
				ret=RECDEL_ENTRIES_REMAINING;
			}
		}
		else
		{
			ret=RECDEL_ENTRIES_REMAINING;
		}
	}

	if(ret==RECDEL_OK && rmdir(directory))
	{
		logp("rmdir %s: %s\n", directory, strerror(errno));
		ret=RECDEL_ERROR;
	}
end:
	if(dirp) closedir(dirp);
	free_w(&fullpath);
	free_w(&directory);
	free_v((void **)&entry);
	return ret;
}
示例#3
0
void rs_filebuf_free(rs_filebuf_t **fb) 
{
	if(!fb || !*fb) return;
	free_w(&((*fb)->buf));
        free_v((void **)fb);
}
示例#4
0
文件: blk.c 项目: EmisFR/burp
void blk_free_content(struct blk *blk)
{
	if(!blk) return;
	free_w(&blk->data);
}
示例#5
0
文件: restore.c 项目: EmisFR/burp
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;
}
示例#6
0
文件: iobuf.c 项目: Lacoste/burp
void iobuf_free_content(struct iobuf *iobuf)
{
	if(!iobuf) return;
	free_w(&iobuf->buf);
	iobuf_init(iobuf);
}
示例#7
0
文件: rubble.c 项目: rubenk/burp
static int recover_working(struct async *as,
	struct sdirs *sdirs, const char *incexc,
	int *resume, struct conf **cconfs)
{
	int ret=-1;
	char msg[256]="";
	char *logpath=NULL;
	struct stat statp;
	char *phase1datatmp=NULL;
	enum recovery_method recovery_method=get_e_recovery_method(
		cconfs[OPT_WORKING_DIR_RECOVERY_METHOD]);

	// The working directory has not finished being populated.
	// Check what to do.
	if(get_fullrealwork(as->asfd, sdirs, cconfs)) goto end;
	if(!sdirs->rworking) goto end;

	log_recovery_method(sdirs, recovery_method);

	if(!(phase1datatmp=get_tmp_filename(sdirs->phase1data)))
		goto end;
	// If there is still a phase1 tmp file...
	if(!lstat(phase1datatmp, &statp)
	  ||
		// ...or phase1 has not even got underway yet...
		(lstat(phase1datatmp, &statp)
		  && lstat(sdirs->phase1data, &statp)
		  && lstat(sdirs->changed, &statp)
		  && lstat(sdirs->unchanged, &statp)))
	{
		// ...phase 1 did not complete - delete everything.
		logp("Phase 1 has not completed.\n");
		recovery_method=RECOVERY_METHOD_DELETE;
	}

	if(recovery_method==RECOVERY_METHOD_DELETE)
	{
		ret=working_delete(as, sdirs, cconfs);
		goto end;
	}

	// We are not deleting the old working directory - open the log inside
	// for appending.
	if(!(logpath=prepend_s(sdirs->rworking, "log"))
	  || log_fzp_set(logpath, cconfs))
		goto end;

	switch(recovery_method)
	{
		case RECOVERY_METHOD_DELETE:
			// Dealt with above.
			break;
		case RECOVERY_METHOD_RESUME:
			ret=working_resume(as, sdirs, incexc, resume, cconfs);
			break;
		case RECOVERY_METHOD_UNSET:
		default:
			snprintf(msg, sizeof(msg),
				"Unknown working_dir_recovery_method: %d\n",
					(int)recovery_method);
			log_and_send(as->asfd, msg);
			break;
	}

end:
	free_w(&logpath);
	free_w(&phase1datatmp);
	log_fzp_set(NULL, cconfs); // fclose the logfzp
	return ret;
}
示例#8
0
static
#endif
int status_client_ncurses_main_loop(struct async *as,
	struct asfd *so_asfd, struct sel *sel,
	const char *orig_client)
{
	int ret=-1;
	char *client=NULL;
	int count=0;
	struct asfd *asfd=NULL;
	struct asfd *sfd=NULL; // Server asfd.
	int reqdone=0;

	if(!sel
	  || !as
	  || !(stdout_asfd=so_asfd)
	  || !(sfd=as->asfd))
	{
		logp("parameters not set up correctly in %s\n", __func__);
		goto error;
	}

	sel->page=PAGE_CLIENT_LIST;

	if(orig_client)
	{
		client=strdup_w(orig_client, __func__);
		sel->page=PAGE_BACKUP_LIST;
	}

	if(json_input_init()) goto end;

	while(1)
	{
		if(need_status(sel) && !reqdone)
		{
			char *req=NULL;
			if(sel->page>PAGE_CLIENT_LIST)
			{
				if(client)
					req=client;
				else if(sel->client)
					req=sel->client->name;
			}
			if(request_status(sfd, req, sel))
				goto error;

			// We only want to start on the client the user gave to
			// us. Freeing it will allow the user to browse other
			// clients thereafter.
			free_w(&client);

			if(actg==ACTION_STATUS_SNAPSHOT)
				reqdone=1;
		}

		if(as->read_write(as))
		{
			// FIX THIS - an exception is thrown when the console
			// is resized.
/*
			if(sfd->want_to_remove)
			{
				sfd->want_to_remove=0;
				continue;
			}
*/
			logp("Exiting main loop\n");
			goto error;
		}

		for(asfd=as->asfd; asfd; asfd=asfd->next)
		{
			while(asfd->rbuf->buf)
			{
				switch(parse_data(asfd, sel, count))
				{
					case 0: break;
					case 1: goto end;
					default: goto error;
				}
				iobuf_free_content(asfd->rbuf);
				if(asfd->parse_readbuf(asfd))
					goto error;
			}

			// Select things if they are not already selected.
			if(sel->client)
			{
				if(!sel->backup)
					sel->backup=sel->client->bu;
			}
			else
				sel->client=sel->clist;
		}

#ifdef HAVE_NCURSES
		if(actg==ACTION_STATUS
		  && update_screen(sel))
			goto error;
		refresh();
#endif

		if(actg==ACTION_STATUS_SNAPSHOT
		  && sel->client)
		{
			if(update_screen(sel))
				goto error;
			stdout_asfd->write_str(stdout_asfd, CMD_GEN, "\n");
			break;
		}
	}

end:
	ret=0;
error:
	json_input_free();
	return ret;
}
示例#9
0
static int process_entry(struct strlist *ig, struct conf **confs)
{
	int ret=-1;
	size_t len1=0;
	char *sav=NULL;
	char **splitstr1=NULL;
        WIN32_FIND_DATA ffd;
        HANDLE hFind=INVALID_HANDLE_VALUE;

	convert_backslashes(&ig->path);
	if(ig->path[strlen(ig->path)-1]!='*')
	{
		if(!(splitstr1=xstrsplit(ig->path, "*", &len1)))
			goto end;
	}
	if(len1>2)
	{
		logp("include_glob error: '%s' contains at least"
			" two '*' which is not currently supported\n",
				ig->path);
		goto end;
	}
	if(len1>1)
	{
		char *tmppath=NULL;
		if(astrcat(&tmppath, splitstr1[0], __func__)
		  || !(sav=strdup_w(tmppath, __func__))
		  || astrcat(&tmppath, "*", __func__))
			goto end;
		hFind=FindFirstFileA(tmppath, &ffd);
		free_w(&tmppath);
	}
	else
		hFind=FindFirstFileA(ig->path, &ffd);

	if(hFind==INVALID_HANDLE_VALUE)
	{
		LPVOID lpMsgBuf;
		DWORD dw=GetLastError(); 
		FormatMessage(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM |
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			dw,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			(LPTSTR)&lpMsgBuf,
			0, NULL );
		logp("Error: %s\n", lpMsgBuf);
		LocalFree(lpMsgBuf);
		goto end;
	}

	do
	{
		if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
		   && strcmp(ffd.cFileName, ".")
		   && strcmp(ffd.cFileName, ".."))
		{
			char *tmppath=NULL;
			if(len1<2)
			{
				if(ig->path[strlen(ig->path)-1]=='*')
				{
					if(!(tmppath=xstrsub(ig->path, 0,
						strlen(ig->path)-1))
					  || astrcat(&tmppath,
						ffd.cFileName, __func__))
							goto end;
				}
				else
					if(!(tmppath=strdup_w(ig->path,
						__func__))) goto end;
			}
			else
			{
				if(astrcat(&tmppath, sav, __func__)
				  || astrcat(&tmppath, ffd.cFileName, __func__)
				  || astrcat(&tmppath, splitstr1[1], __func__))
					goto end;
			}
			if(add_to_strlist(confs[OPT_INCLUDE], tmppath, 1))
				goto end;
			free_w(&tmppath);
		}
	}
	while(FindNextFileA(hFind, &ffd)!=0);

	FindClose(hFind);
	ret=0;
end:
	if(splitstr1)
	{
		free_w(&sav);
		xfree_list(splitstr1, len1);
	}
	return ret;
}
示例#10
0
int backup_phase1_server_all(struct async *as,
	struct sdirs *sdirs, struct conf **confs)
{
	int ret=-1;
	struct sbuf *sb=NULL;
	char *phase1tmp=NULL;
	struct asfd *asfd=as->asfd;
	struct manio *manio=NULL;
	enum protocol protocol=get_protocol(confs);
	struct cntr *cntr=get_cntr(confs);

	logp("Begin phase1 (file system scan)\n");

	if(!(phase1tmp=get_tmp_filename(sdirs->phase1data))
	  || !(manio=manio_open_phase1(phase1tmp,
		comp_level(get_int(confs[OPT_COMPRESSION])), protocol))
	  || !(sb=sbuf_alloc(protocol)))
		goto error;

	while(1)
	{
		sbuf_free_content(sb);
		switch(sbuf_fill_from_net(sb, asfd, NULL, NULL, cntr))
		{
			case 0: break;
			case 1: // Last thing the client sends is
				// 'backupphase2', and it wants an 'ok' reply.
				if(asfd->write_str(asfd, CMD_GEN, "ok")
				  || send_msg_fzp(manio->fzp, CMD_GEN,
					"phase1end", strlen("phase1end")))
						goto error;
				goto end;
			case -1:
			default: goto error;
		}
		if(write_status(CNTR_STATUS_SCANNING, sb->path.buf, cntr)
		  || manio_write_sbuf(manio, sb))
			goto error;
		cntr_add_phase1(cntr, sb->path.cmd, 0);

		if(sbuf_is_filedata(sb))
		{
			cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
				(uint64_t)sb->statp.st_size, 0);
		}
	}

end:
	if(manio_close(&manio))
	{
		logp("error closing %s in backup_phase1_server\n", phase1tmp);
		goto error;
	}

	if(check_quota(as, cntr,
		get_uint64_t(confs[OPT_HARD_QUOTA]),
		get_uint64_t(confs[OPT_SOFT_QUOTA])))
			goto error;

	// Possible rename race condition is of no consequence here, because
	// the working directory will always get deleted if phase1 is not
	// complete.
	if(do_rename(phase1tmp, sdirs->phase1data))
		goto error;

	//cntr_print(p1cntr, cntr, ACTION_BACKUP);

	logp("End phase1 (file system scan)\n");
	ret=0;
error:
	free_w(&phase1tmp);
	manio_close(&manio);
	sbuf_free(&sb);
	return ret;
}
示例#11
0
文件: auth.c 项目: grke/burp
int authorise_server(struct asfd *asfd,
	struct conf **globalcs, struct conf **cconfs)
{
	int ret=-1;
	char *cp=NULL;
	char *password=NULL;
	char *cname=NULL;
	char whoareyou[256]="";
	struct iobuf *rbuf=asfd->rbuf;
	const char *peer_version=NULL;
	if(asfd->read(asfd))
	{
		logp("unable to read initial message\n");
		goto end;
	}
	if(rbuf->cmd!=CMD_GEN || strncmp_w(rbuf->buf, "hello"))
	{
		iobuf_log_unexpected(rbuf, __func__);
		goto end;
	}
	// String may look like...
	// "hello"
	// "hello:(version)"
	// (version) is a version number
	if((cp=strchr(rbuf->buf, ':')))
	{
		cp++;
		if(cp && set_string(cconfs[OPT_PEER_VERSION], cp))
			goto end;
	}
	iobuf_free_content(rbuf);

	snprintf(whoareyou, sizeof(whoareyou), "whoareyou");
	peer_version=get_string(cconfs[OPT_PEER_VERSION]);
	if(peer_version)
	{
		long min_ver=0;
		long cli_ver=0;
		if((min_ver=version_to_long("1.3.2"))<0
		  || (cli_ver=version_to_long(peer_version))<0)
			return -1;
		// Stick the server version on the end of the whoareyou string.
		// if the client version is recent enough.
		if(min_ver<=cli_ver)
		 snprintf(whoareyou, sizeof(whoareyou),
			"whoareyou:%s", PACKAGE_VERSION);
	}

	if(asfd->write_str(asfd, CMD_GEN, whoareyou)
	  || asfd->read(asfd))
	{
		logp("unable to get client name\n");
		goto end;
	}

	if(!(cname=strdup_w(rbuf->buf, __func__)))
		goto end;
	if(!get_int(globalcs[OPT_CNAME_FQDN]))
		strip_fqdn(&cname);
	if(get_int(globalcs[OPT_CNAME_LOWERCASE]))
		strlwr(cname);

	if(set_string(cconfs[OPT_CNAME], cname))
		goto end;
	iobuf_free_content(rbuf);

	if(asfd->write_str(asfd, CMD_GEN, "okpassword")
	  || asfd->read(asfd))
	{
		logp("unable to get password for client %s\n",
			get_string(cconfs[OPT_CNAME]));
		goto end;
	}
	password=rbuf->buf;
	iobuf_init(rbuf);

	if(check_client_and_password(globalcs, password, cconfs))
		goto end;

	if(get_int(cconfs[OPT_VERSION_WARN]))
		version_warn(asfd, get_cntr(globalcs), cconfs);

	logp("auth ok for: %s%s\n", get_string(cconfs[OPT_CNAME]),
		get_int(cconfs[OPT_PASSWORD_CHECK])?
			"":" (no password needed)");

	if(asfd->write_str(asfd, CMD_GEN, "ok"))
		goto end;

	ret=0;
end:
	iobuf_free_content(rbuf);
	free_w(&password);
	free_w(&cname);
	return ret;
}
示例#12
0
文件: dpth.c 项目: Kalimeiro/burp
void dpth_free(struct dpth **dpth)
{
	if(!dpth || !*dpth) return;
	free_w(&((*dpth)->base_path));
	free_v((void **)dpth);
}
示例#13
0
文件: json_input.c 项目: Shloub/burp
static int input_string(void *ctx, const unsigned char *val, size_t len)
{
	char *str;
	if(!(str=(char *)malloc_w(len+2, __func__)))
		return 0;
	snprintf(str, len+1, "%s", val);

	if(in_counters)
	{
		if(!strcmp(lastkey, "name"))
		{
			// Ignore 'name' in a counters object. We use 'type'
			// instead.
		}
		else if(!strcmp(lastkey, "type"))
		{
			if(!current) goto error;
			cntr_ent=current->cntr->ent[(uint8_t)*str];
		}
		else
		{
			goto error;
		}
		goto end;
	}
	else if(!strcmp(lastkey, "name"))
	{
		if(cnew) goto error;
		if(!(current=cstat_get_by_name(*cslist, str)))
		{
			if(!(cnew=cstat_alloc())
			  || cstat_init(cnew, str, NULL))
				goto error;
			current=cnew;
		}
		goto end;
	}
	else if(!strcmp(lastkey, "run_status"))
	{
		if(!current) goto error;
		current->run_status=run_str_to_status(str);
		goto end;
	}
	else if(!strcmp(lastkey, "phase"))
	{
		if(!current) goto error;
		current->cntr->cntr_status=cntr_str_to_status(str);
		goto end;
	}
	else if(!strcmp(lastkey, "flags"))
	{
		if(!current) goto error;
		if(is_wrap(str, "hardlinked", BU_HARDLINKED)
		  || is_wrap(str, "deletable", BU_DELETABLE)
		  || is_wrap(str, "working", BU_WORKING)
		  || is_wrap(str, "finishing", BU_FINISHING)
		  || is_wrap(str, "current", BU_CURRENT)
		  || is_wrap(str, "manifest", BU_MANIFEST))
			goto end;
	}
	else if(!strcmp(lastkey, "counters")) // Do we need this?
	{
		goto end;
	}
	else if(!strcmp(lastkey, "list"))
	{
		if(is_wrap(str, "backup", BU_LOG_BACKUP)
		  || is_wrap(str, "restore", BU_LOG_RESTORE)
		  || is_wrap(str, "verify", BU_LOG_VERIFY)
		  || is_wrap(str, "backup_stats", BU_STATS_BACKUP)
		  || is_wrap(str, "restore_stats", BU_STATS_RESTORE)
		  || is_wrap(str, "verify_stats", BU_STATS_VERIFY))
			goto end;
	}
	else if(!strcmp(lastkey, "logs"))
	{
		goto end;
	}
	else if(!strcmp(lastkey, "logline"))
	{
		goto end;
	}
	else if(!strcmp(lastkey, "backup")
	  || !strcmp(lastkey, "restore")
	  || !strcmp(lastkey, "verify")
	  || !strcmp(lastkey, "backup_stats")
	  || !strcmp(lastkey, "restore_stats")
	  || !strcmp(lastkey, "verify_stats"))
	{
		// Log file contents.
		if(lline_add(&ll_list, str))
			goto error;
		goto end;
	}
error:
	logp("Unexpected string: %s %s\n", lastkey, str);
	free_w(&str);
        return 0;
end:
	free_w(&str);
	return 1;
}
示例#14
0
文件: json_input.c 项目: Shloub/burp
static void merge_bu_lists(void)
{
	struct bu *n;
	struct bu *o;
	struct bu *lastn=NULL;
	struct bu *lasto=NULL;

	for(o=current->bu; o; )
	{
		int found_in_new=0;
		lastn=NULL;
		for(n=bu_list; n; n=n->next)
		{
			if(o->bno==n->bno)
			{
				// Found o in new list.
				// Copy the fields from new to old.
				found_in_new=1;
				o->flags=n->flags;
				free_w(&o->timestamp);
				o->timestamp=n->timestamp;
				n->timestamp=NULL;

				// Remove it from new list.
				if(lastn)
				{
					lastn->next=n->next;
					if(n->next) n->next->prev=lastn;
				}
				else
				{
					bu_list=n->next;
					if(bu_list) bu_list->prev=NULL;
				}
				bu_free(&n);
				n=lastn;
				break;
			}
			lastn=n;
		}
		if(!found_in_new)
		{
			// Could not find o in new list.
			// Remove it from old list.
			if(lasto)
			{
				lasto->next=o->next;
				if(o->next) o->next->prev=lasto;
			}
			else
			{
				current->bu=o->next;
				if(current->bu) current->bu->prev=NULL;
			}
			// Need to reset if the one that was removed was
			// selected in ncurses.
			if(o==*sselbu) *sselbu=NULL;
			bu_free(&o);
			o=lasto;
		}
		lasto=o;
		if(o) o=o->next;
	}

	// Now, new list only has entries missing from old list.
	n=bu_list;
	lastn=NULL;
	while(n)
	{
		o=current->bu;
		lasto=NULL;
		while(o && n->bno < o->bno)
		{
			lasto=o;
			o=o->next;
		}
		// Found the place to insert it.
		if(lasto)
		{
			lasto->next=n;
			n->prev=lasto;
		}
		else
		{
			if(current->bu) current->bu->prev=n;
			current->bu=n;
			current->bu->prev=NULL;
		}
		lastn=n->next;
		n->next=o;
		n=lastn;
	}
}
示例#15
0
文件: sdirs.c 项目: Sherlock221B/burp
static int free_prepend_s(char **dst, const char *a, const char *b)
{
	free_w(dst);
	return !(*dst=prepend_s(a, b));
}
示例#16
0
文件: xattr.c 项目: Kalimeiro/burp
static int do_set_xattr_bsd(struct asfd *asfd,
	const char *path, struct stat *statp,
	const char *xattrtext, size_t xlen, struct conf *conf)
{
	int ret=-1;
	size_t l=0;
	char *data=NULL;
	char *value=NULL;
	char *nspace=NULL;

	data=(char *)xattrtext;
	l=xlen;
	while(l>0)
	{
		int cnt;
		ssize_t vlen=0;
		int cnspace=0;
		char *name=NULL;

		if(!(nspace=get_next_str(asfd, &data, &l, conf, &vlen, path))
		  || !(value=get_next_str(asfd, &data, &l, conf, &vlen, path)))
			goto end;

		// Need to split the name into two parts.
		if(!(name=strchr(nspace, '.')))
		{
			logw(conf,
			  "could not split %s into namespace and name on %s\n",
				nspace, path);
			goto end;
		}
		*name='\0';
		name++;

		if(extattr_string_to_namespace(nspace, &cnspace))
		{
			logw(conf,
				"could not convert %s into namespace on %s",
				nspace, path);
			goto end;
		}

		//printf("set_link: %d %s %s %s\n", cnspace, nspace, name, value);
		if((cnt=extattr_set_link(path,
			cnspace, name, value, vlen))!=vlen)
		{
			logw(conf,
				"extattr_set_link error on %s %d!=vlen: %s\n",
				path, strerror(errno));
			goto end;
		}

		free_w(&nspace);
		free_w(&value);
	}
	ret=0;
end:
	free_w(&nspace);
	free_w(&value);
	return ret;
}
示例#17
0
文件: link.c 项目: EmisFR/burp
int recursive_hardlink(const char *src, const char *dst, struct conf **confs)
{
	int n=-1;
	int ret=0;
	struct dirent **dir;
	char *tmp=NULL;
	char *fullpatha=NULL;
	char *fullpathb=NULL;
	//logp("in rec hl: %s %s\n", src, dst);
	if(!(tmp=prepend_s(dst, "dummy"))) return -1;
	if(mkpath(&tmp, dst))
	{
		logp("could not mkpath for %s\n", tmp);
		free_w(&tmp);
		return -1;
	}
	free_w(&tmp);

	if((n=scandir(src, &dir, 0, 0))<0)
	{
		logp("recursive_hardlink scandir %s: %s\n",
			src, strerror(errno));
		return -1;
	}
	while(n--)
	{
		struct stat statp;
		if(dir[n]->d_ino==0
		  || !strcmp(dir[n]->d_name, ".")
		  || !strcmp(dir[n]->d_name, ".."))
			{ free(dir[n]); continue; }
		free_w(&fullpatha);
		free_w(&fullpathb);
		if(!(fullpatha=prepend_s(src, dir[n]->d_name))
		  || !(fullpathb=prepend_s(dst, dir[n]->d_name)))
			break;

#ifdef _DIRENT_HAVE_D_TYPE
// Faster evaluation on most systems.
		if(dir[n]->d_type==DT_DIR)
		{
			if(recursive_hardlink(fullpatha, fullpathb, confs))
				break;
		}
		else
#endif
		// Otherwise, we have to do an lstat() anyway, because we
		// will need to check the number of hardlinks in do_link().
		if(lstat(fullpatha, &statp))
		{
			logp("could not lstat %s\n", fullpatha);
		}
		else if(S_ISDIR(statp.st_mode))
		{
			if(recursive_hardlink(fullpatha, fullpathb, confs))
				break;
		}
		else
		{
			//logp("hardlinking %s to %s\n", fullpathb, fullpatha);
			if(write_status(CNTR_STATUS_SHUFFLING, fullpathb,
				get_cntr(confs))
			  || do_link(fullpatha, fullpathb, &statp, confs,
				0 /* do not overwrite target */))
				break;
		}
		free(dir[n]);
	}
	if(n>0)
	{
		ret=-1;
		for(; n>0; n--) free(dir[n]);
	}
	free(dir);

	free_w(&fullpatha);
	free_w(&fullpathb);

	return ret;
}
示例#18
0
文件: xattr.c 项目: Kalimeiro/burp
int get_xattr(struct asfd *asfd, const char *path, struct stat *statp,
	char **xattrtext, size_t *xlen, struct conf *conf)
{
	char *z=NULL;
	size_t len=0;
	int have_acl=0;
	char *toappend=NULL;
	char *xattrlist=NULL;
	size_t totallen=0;
	size_t maxlen=0xFFFFFFFF/2;

	if((len=llistxattr(path, NULL, 0))<=0)
	{
		logw(asfd, conf, "could not llistxattr '%s': %d\n", path, len);
		return 0; // carry on
	}
	if(!(xattrlist=(char *)malloc(len+1)))
	{
		log_out_of_memory(__func__);
		return -1;
	}
	memset(xattrlist, 0, len+1);
	if((len=llistxattr(path, xattrlist, len))<=0)
	{
		logw(asfd, conf, "could not llistxattr '%s': %d\n", path, len);
		free_w(&xattrlist);
		return 0; // carry on
	}
	xattrlist[len]='\0';

	if(xattrtext && *xattrtext)
	{
		// Already have some meta text, which means that some
		// ACLs were set.
		have_acl++;
	}

	z=xattrlist;
	for(z=xattrlist; len > (size_t)(z-xattrlist)+1; z=strchr(z, '\0')+1)
	{
		char tmp1[9];
		char tmp2[9];
		char *val=NULL;
		size_t vlen=0;
		size_t zlen=0;

		if((zlen=strlen(z))>maxlen)
		{
                	logw(asfd, conf, "xattr element of '%s' too long: %d\n",
				path, zlen);
			free_w(&toappend);
			break;
		}

		if(have_acl)
		{
			int c=0;
			int skip=0;
			// skip xattr entries that were already saved as ACLs.
			for(c=0; xattr_acl_skiplist[c]; c++)
			{
				if(!strcmp(z, xattr_acl_skiplist[c]))
				{
					skip++;
					break;
				}
			}
			if(skip) continue;
		}

		if((vlen=lgetxattr(path, z, NULL, 0))<=0)
		{
			logw(asfd, conf, "could not lgetxattr on %s for %s: %d\n",
				path, z, vlen);
			continue;
		}
		if(!(val=(char *)malloc(vlen+1)))
		{
			log_out_of_memory(__func__);
			free_w(&xattrlist);
			free_w(&toappend);
			return -1;
		}
		if((vlen=lgetxattr(path, z, val, vlen))<=0)
		{
			logw(asfd, conf, "could not lgetxattr %s for %s: %d\n",
				path, z, vlen);
			free_w(&val);
			continue;
		}
		val[vlen]='\0';

		if(vlen>maxlen)
		{
                	logw(asfd, conf, "xattr value of '%s' too long: %d\n",
				path, vlen);
			free_w(&toappend);
			free_w(&val);
			break;
		}

		snprintf(tmp1, sizeof(tmp1), "%08X", (unsigned int)zlen);
		snprintf(tmp2, sizeof(tmp2), "%08X", (unsigned int)vlen);
		if(!(toappend=prepend_len(toappend, totallen,
			tmp1, 8, "", 0, &totallen))
		  || !(toappend=prepend_len(toappend, totallen,
			z, zlen, "", 0, &totallen))
		  || !(toappend=prepend_len(toappend, totallen,
			tmp2, 8, "", 0, &totallen))
		  || !(toappend=prepend_len(toappend, totallen,
			val, vlen, "", 0, &totallen)))
		{
			log_out_of_memory(__func__);
			free_w(&val);
			free_w(&xattrlist);
			return -1;
		}
		free_w(&val);

		if(totallen>maxlen)
		{
                	logw(asfd, conf,
				"xattr length of '%s' grew too long: %d\n",
				path, totallen);
			free_w(&val);
			free_w(&toappend);
			free_w(&xattrlist);
			return 0; // carry on
		}
	}

	if(toappend)
	{
		char tmp3[10];
		snprintf(tmp3, sizeof(tmp3), "%c%08X",
			META_XATTR, (unsigned int)totallen);
		if(!(*xattrtext=prepend_len(*xattrtext, *xlen,
			tmp3, 9, "", 0, xlen))
		  || !(*xattrtext=prepend_len(*xattrtext, *xlen,
			toappend, totallen, "", 0, xlen)))
		{
			log_out_of_memory(__func__);
			free_w(&toappend);
			free_w(&xattrlist);
			return -1;
		}
		free_w(&toappend);
	}
	free_w(&xattrlist);
	return 0;
}
示例#19
0
VOID CacheBlockFree(PBLKCACHE pc, LPVOID lpv)
{
    if (IsCacheBlock(pc, lpv)) {
        PBLKHEADER pbh = (PBLKHEADER)lpv - 1;

#ifdef DEBUG
        PBLKHEADER pbhf = pc->pCacheHead;
        PBLKHEADER pbhLast = NULL;
        
        // remove from the list of working nodes
        while (NULL != pbhf && pbhf != pbh) {
            pbhLast = pbhf;
            pbhf = pbhf->pNext;
        }

        if (NULL != pbhf) {

            // link in pbh->pNext into a worklist

            LINK_WORKLIST(pc, pbh->pNext, pbhLast); 
        } 
        else {
            LOGDEBUG(LOG_ALWAYS, ("Alert! CacheBlockFree - invalid ptr\n"));
            return;
        }
        
        pbhf = pc->pCacheFree;
        pbhLast = NULL;
        
#else
        PBLKHEADER pbhf = pc->pCacheFree;
        PBLKHEADER pbhLast = NULL;
#endif
        // list of free nodes

        // insert in order
        while (NULL != pbhf) {

            // most often case - append from the right
            
            if (((LPBYTE)pbhf + pbhf->dwSize) == (LPBYTE)pbh) {
                
                pbhf->dwSize += pbh->dwSize; // adjust the size

                // now see if we need compact
                if (NULL != pbhLast) {
                    if (((LPBYTE)pbhf + pbhf->dwSize) == (LPBYTE)pbhLast) {
                        // consolidate
                        pbhLast->dwSize += pbhf->dwSize;
                        pbhLast->pNext   = pbhf->pNext;
                    }
                }

                return;
            }
            else
            // check if we can append from the left
            if (((LPBYTE)pbh + pbh->dwSize) == (LPBYTE)pbhf) {

                pbh->dwSize += pbhf->dwSize;    // adjust the size
                pbh->pNext   = pbhf->pNext;     // next ptr too

                // now also check the next free ptr so we can compact 
                // the next ptr has lesser address

                if (NULL != pbh->pNext) {
                    pbhf = pbh->pNext;

                    if (((LPBYTE)pbhf + pbhf->dwSize) == (LPBYTE)pbh) {

                        pbhf->dwSize += pbh->dwSize;
                        pbh = pbhf;
                    }
                }

                LINK_FREELIST(pc, pbh, pbhLast);

                return;
            }

            // check for address

            if (pbh > pbhf) { 
                // we have to link-in a standalone block
                break;
            }

            pbhLast = pbhf;
            pbhf = pbhf->pNext; // on to the next block
        }

        // LOGDEBUG(LOG_ALWAYS, ("Param Map Cache: OUT-OF-ORDER free!!!\n"));

        pbh->pNext = pbhf;

        LINK_FREELIST(pc, pbh, pbhLast);
        
    }
    else {
        free_w(lpv);
    }
}
示例#20
0
// returns 1 for finished ok.
static int do_stuff_to_receive(struct asfd *asfd,
	struct sdirs *sdirs, struct conf **cconfs,
	struct sbuf *rb, struct fzp *chfp,
	struct dpth *dpth, char **last_requested)
{
	struct iobuf *rbuf=asfd->rbuf;

	iobuf_free_content(rbuf);
	// This also attempts to write anything in the write buffer.
	if(asfd->as->read_write(asfd->as))
	{
		logp("error in %s\n", __func__);
		return -1;
	}

	if(!rbuf->buf) return 0;

	if(rbuf->cmd==CMD_MESSAGE
	  || rbuf->cmd==CMD_WARNING)
	{
		log_recvd(rbuf, cconfs, 0);
		return 0;
	}

	if(rb->protocol1->fzp)
	{
		// Currently writing a file (or meta data)
		switch(rbuf->cmd)
		{
			case CMD_APPEND:
				if(deal_with_receive_append(asfd, rb, cconfs))
					goto error;
				return 0;
			case CMD_END_FILE:
				if(deal_with_receive_end_file(asfd, sdirs, rb,
					chfp, cconfs, last_requested))
						goto error;
				return 0;
			default:
				iobuf_log_unexpected(rbuf, __func__);
				goto error;
		}
	}

	// Otherwise, expecting to be told of a file to save.
	switch(rbuf->cmd)
	{
		case CMD_DATAPTH:
			iobuf_move(&rb->protocol1->datapth, rbuf);
			return 0;
		case CMD_ATTRIBS:
			iobuf_move(&rb->attr, rbuf);
			return 0;
		case CMD_GEN:
			if(!strcmp(rbuf->buf, "okbackupphase2end"))
				goto end_phase2;
			iobuf_log_unexpected(rbuf, __func__);
			goto error;
		case CMD_INTERRUPT:
			// Interrupt - forget about the last requested
			// file if it matches. Otherwise, we can get
			// stuck on the select in the async stuff,
			// waiting for something that will never arrive.
			if(*last_requested
			  && !strcmp(rbuf->buf, *last_requested))
				free_w(last_requested);
			return 0;
		default:
			break;
	}
	if(cmd_is_filedata(rbuf->cmd))
	{
		if(deal_with_filedata(asfd, sdirs, rb, rbuf, dpth, cconfs))
			goto error;
		return 0;
	}
	iobuf_log_unexpected(rbuf, __func__);

error:
	return -1;
end_phase2:
	return 1;
}
示例#21
0
文件: find.c 项目: pkdevbox/burp
static int found_directory(struct asfd *asfd,
	FF_PKT *ff_pkt, struct conf **confs,
	char *fname, dev_t parent_device, bool top_level)
{
	int ret=-1;
	char *link=NULL;
	size_t link_len;
	size_t len;
	int nbret=0;
	int count=0;
	dev_t our_device;
	struct dirent **nl=NULL;

	our_device=ff_pkt->statp.st_dev;

	if((nbret=nobackup_directory(get_strlist(confs[OPT_NOBACKUP]),
		ff_pkt->fname)))
	{
		if(nbret<0) goto end; // Error.
		ret=0; // Do not back it up.
		goto end;
	}

	/* Build a canonical directory name with a trailing slash in link var */
	len=strlen(fname);
	link_len=len+200;
	if(!(link=(char *)malloc_w(link_len+2, __func__)))
		goto end;
	snprintf(link, link_len, "%s", fname);

	/* Strip all trailing slashes */
	while(len >= 1 && IsPathSeparator(link[len - 1])) len--;
	/* add back one */
	link[len++]='/';
	link[len]=0;

	ff_pkt->link=link;
	ff_pkt->type=FT_DIR;

#if defined(HAVE_WIN32)
	windows_reparse_point_fiddling(ff_pkt);
#endif

	if(send_file_w(asfd, ff_pkt, top_level, confs))
		goto end;
	if(ff_pkt->type==FT_REPARSE || ff_pkt->type==FT_JUNCTION)
	{
		// Ignore.
		ret=0;
		goto end;
	}

	if(top_level
	  || (parent_device!=ff_pkt->statp.st_dev
#if defined(HAVE_WIN32)
		|| ff_pkt->statp.st_rdev==WIN32_MOUNT_POINT
#endif
		))
	{
		if(fstype_excluded(asfd, confs, ff_pkt->fname))
		{
			ret=send_file_w(asfd, ff_pkt, top_level, confs);
			goto end;
		}
		if(!top_level && !fs_change_is_allowed(confs, ff_pkt->fname))
		{
			ff_pkt->type=FT_NOFSCHG;
			// Just backup the directory and return.
			ret=send_file_w(asfd, ff_pkt, top_level, confs);
			goto end;
		}
	}

	ff_pkt->link=ff_pkt->fname;

	errno=0;
	switch(entries_in_directory_alphasort(fname,
		&nl, &count, get_int(confs[OPT_ATIME])))
	{
		case 0: break;
		case 1:
			ff_pkt->type=FT_NOOPEN;
			ret=send_file_w(asfd, ff_pkt, top_level, confs);
		default:
			goto end;
	}

	if(nl)
	{
		if(process_entries_in_directory(asfd, nl, count,
			&link, len, &link_len, confs, ff_pkt, our_device))
				goto end;
	}
	ret=0;
end:
	free_w(&link);
	free_v((void **)&nl);
	return ret;
}
示例#22
0
int backup_phase2_server_protocol1(struct async *as, struct sdirs *sdirs,
	const char *incexc, int resume, struct conf **cconfs)
{
	int ret=0;
	struct manio *p1manio=NULL;
	struct dpth *dpth=NULL;
	char *deltmppath=NULL;
	char *last_requested=NULL;
	// Where to write changed data.
	// Data is not getting written to a compressed file.
	// This is important for recovery if the power goes.
	struct fzp *chfp=NULL;
	struct fzp *ucfp=NULL; // unchanged data
	struct fzp *cmanfp=NULL; // previous (current) manifest.
	struct sbuf *cb=NULL; // file list in current manifest
	struct sbuf *p1b=NULL; // file list from client
	struct sbuf *rb=NULL; // receiving file from client
	struct asfd *asfd=as->asfd;
	int breaking=0;
	int breakcount=0;
	if(get_int(cconfs[OPT_BREAKPOINT])>=2000
	  && get_int(cconfs[OPT_BREAKPOINT])<3000)
	{
		breaking=get_int(cconfs[OPT_BREAKPOINT]);
		breakcount=breaking-2000;
	}

	logp("Begin phase2 (receive file data)\n");

	if(!(dpth=dpth_alloc())
	  || dpth_protocol1_init(dpth, sdirs->currentdata,
		get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS])))
			goto error;

	if(open_previous_manifest(&cmanfp, sdirs, incexc, cconfs))
		goto error;

	if(get_int(cconfs[OPT_DIRECTORY_TREE]))
	{
		// Need to make sure we do not try to create a path that is
		// too long.
		if(build_path_w(sdirs->treepath)) goto error;
		treepathlen=strlen(sdirs->treepath);
		init_fs_max(sdirs->treepath);
	}

	if(!(p1manio=manio_alloc())
	  || manio_init_read(p1manio, sdirs->phase1data)
	  || !(cb=sbuf_alloc(cconfs))
	  || !(p1b=sbuf_alloc(cconfs))
	  || !(rb=sbuf_alloc(cconfs)))
		goto error;

	manio_set_protocol(p1manio, PROTO_1);

	if(resume && do_resume(p1manio, sdirs, dpth, cconfs))
		goto error;

	// Unchanged and changed should now be truncated correctly, we just
	// have to open them for appending.
	if(!(ucfp=fzp_open(sdirs->unchanged, "a+b"))
	  || !(chfp=fzp_open(sdirs->changed, "a+b")))
		goto error;

	if(manio_closed(p1manio)
	  && manio_open_next_fpath(p1manio))
		goto error;

	while(1)
	{
		if(breaking)
		{
			if(breakcount--==0) return breakpoint(cconfs, __func__);
		}

		//printf("in loop, %s %s %c\n",
		//	cmanfp?"got cmanfp":"no cmanfp",
		//	rb->path.buf?:"no rb->path",
	 	//	rb->path.buf?'X':rb->path.cmd);
		if(write_status(CNTR_STATUS_BACKUP,
			rb->path.buf?rb->path.buf:p1b->path.buf, cconfs))
				goto error;
		if(last_requested
		  || manio_closed(p1manio)
		  || asfd->writebuflen)
		{
			switch(do_stuff_to_receive(asfd, sdirs,
				cconfs, rb, chfp, dpth, &last_requested))
			{
				case 0: break;
				case 1: goto end; // Finished ok.
				case -1: goto error;
			}
		}

		switch(do_stuff_to_send(asfd, p1b, &last_requested))
		{
			case 0: break;
			case 1: continue;
			case -1: goto error;
		}

		if(manio_closed(p1manio)) continue;

		sbuf_free_content(p1b);

		switch(manio_sbuf_fill_phase1(p1manio, asfd,
			p1b, NULL, sdirs, cconfs))
		{
			case 0: break;
			case 1: manio_close(p1manio);
				if(asfd->write_str(asfd,
				  CMD_GEN, "backupphase2end")) goto error;
				break;
			case -1: goto error;
		}

		if(!cmanfp)
		{
			// No old manifest, need to ask for a new file.
			if(process_new(sdirs, cconfs, p1b, ucfp))
				goto error;
			continue;
		}

		// Have an old manifest, look for it there.

		// Might already have it, or be ahead in the old
		// manifest.
		if(cb->path.buf) switch(maybe_process_file(asfd,
			sdirs, cb, p1b, ucfp, cconfs))
		{
			case 0: break;
			case 1: continue;
			case -1: goto error;
		}

		while(cmanfp)
		{
			sbuf_free_content(cb);
			switch(sbufl_fill(cb, asfd, cmanfp, cconfs))
			{
				case 0: break;
				case 1: fzp_close(&cmanfp);
					if(process_new(sdirs, cconfs, p1b,
						ucfp)) goto error;
					continue;
				case -1: goto error;
			}
			switch(maybe_process_file(asfd, sdirs,
				cb, p1b, ucfp, cconfs))
			{
				case 0: continue;
				case 1: break;
				case -1: goto error;
			}
			break;
		}
	}

error:
	ret=-1;
end:
	if(fzp_close(&chfp))
	{
		logp("error closing %s in %s\n", sdirs->changed, __func__);
		ret=-1;
	}
	if(fzp_close(&ucfp))
	{
		logp("error closing %s in %s\n", sdirs->unchanged, __func__);
		ret=-1;
	}
	free_w(&deltmppath);
	sbuf_free(&cb);
	sbuf_free(&p1b);
	sbuf_free(&rb);
	manio_free(&p1manio);
	fzp_close(&cmanfp);
	dpth_free(&dpth);
	if(!ret) unlink(sdirs->phase1data);

	logp("End phase2 (receive file data)\n");

	return ret;
}
示例#23
0
文件: restore.c 项目: EmisFR/burp
static int restore_special(struct asfd *asfd, struct sbuf *sb,
	const char *fname, enum action act, struct cntr *cntr,
	enum protocol protocol)
{
	int ret=0;
	char *rpath=NULL;
#ifdef HAVE_WIN32
	logw(asfd, cntr, "Cannot restore special files to Windows: %s\n", fname);
	goto end;
#else
	struct stat statp=sb->statp;

	if(act==ACTION_VERIFY)
	{
		cntr_add(cntr, CMD_SPECIAL, 1);
		return 0;
	}

	if(build_path(fname, "", &rpath, NULL))
	{
		// failed - do a warning
		if(restore_interrupt(asfd, sb,
			build_msg("build path failed: %s", fname),
			cntr, protocol))
				ret=-1;
		goto end;
	}
	if(S_ISFIFO(statp.st_mode))
	{
		if(mkfifo(rpath, statp.st_mode) && errno!=EEXIST)
			do_logw(asfd, cntr,
				"Cannot make fifo: %s\n", strerror(errno));
		else
		{
			attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
			cntr_add(cntr, CMD_SPECIAL, 1);
		}
	}
	else if(S_ISSOCK(statp.st_mode))
	{
		if(mksock(rpath))
			do_logw(asfd, cntr,
				"Cannot make socket: %s\n", strerror(errno));
		else
		{
			attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
			cntr_add(cntr, CMD_SPECIAL, 1);
		}
	}
#ifdef S_IFDOOR     // Solaris high speed RPC mechanism
	else if (S_ISDOOR(statp.st_mode))
		do_logw(asfd, cntr,
			"Skipping restore of door file: %s\n", fname);
#endif
#ifdef S_IFPORT     // Solaris event port for handling AIO
	else if (S_ISPORT(statp.st_mode))
		do_logw(asfd, cntr,
			"Skipping restore of event port file: %s\n", fname);
#endif
	else if(mknod(fname, statp.st_mode, statp.st_rdev) && errno!=EEXIST)
		do_logw(asfd, cntr, "Cannot make node: %s\n", strerror(errno));
	else
	{
		attribs_set(asfd, rpath, &statp, sb->winattr, cntr);
		cntr_add(cntr, CMD_SPECIAL, 1);
	}
#endif
end:
	free_w(&rpath);
	return ret;
}
示例#24
0
static int jiggle(struct sdirs *sdirs, struct fdirs *fdirs, struct sbuf *sb,
	int hardlinked_current, const char *deltabdir, const char *deltafdir,
	const char *sigpath, FILE **delfp, struct conf **cconfs)
{
	int ret=-1;
	struct stat statp;
	char *oldpath=NULL;
	char *newpath=NULL;
	char *finpath=NULL;
	char *deltafpath=NULL;
	const char *datapth=sb->protocol1->datapth.buf;

	// If the previous backup was a hardlinked_archive, there will not be
	// a currentdup directory - just directly use the file in the previous
	// backup.
	if(!(oldpath=prepend_s(hardlinked_current?
		sdirs->currentdata:fdirs->currentdupdata, datapth))
	  || !(newpath=prepend_s(fdirs->datadirtmp, datapth))
	  || !(finpath=prepend_s(fdirs->datadir, datapth))
	  || !(deltafpath=prepend_s(deltafdir, datapth)))
		goto end;

	if(!lstat(finpath, &statp) && S_ISREG(statp.st_mode))
	{
		// Looks like an interrupted jiggle
		// did this file already.
		static int donemsg=0;
		if(!lstat(deltafpath, &statp) && S_ISREG(statp.st_mode))
		{
			logp("deleting unneeded forward delta: %s\n",
				deltafpath);
			unlink(deltafpath);
		}
		if(!donemsg)
		{
			logp("skipping already present file: %s\n", finpath);
			logp("to save log space, skips of other already present files will not be logged\n");
			donemsg++;
		}
	}
	else if(mkpath(&finpath, fdirs->datadir))
	{
		logp("could not create path for: %s\n", finpath);
		goto end;
	}
	else if(mkpath(&newpath, fdirs->datadirtmp))
	{
		logp("could not create path for: %s\n", newpath);
		goto end;
	}
	else if(!lstat(deltafpath, &statp) && S_ISREG(statp.st_mode))
	{
		int lrs;
		char *infpath=NULL;

		// Got a forward patch to do.
		// First, need to gunzip the old file,
		// otherwise the librsync patch will take
		// forever, because it will be doing seeks
		// all over the place, and gzseeks are slow.
	  	if(!(infpath=prepend_s(deltafdir, "inflate")))
		{
			log_out_of_memory(__func__);
			goto end;
		}

		//logp("Fixing up: %s\n", datapth);
		if(inflate_or_link_oldfile(oldpath, infpath,
			sb->compression, cconfs))
		{
			logp("error when inflating old file: %s\n", oldpath);
			free(infpath);
			goto end;
		}

		if((lrs=do_patch(NULL, infpath, deltafpath, newpath,
			get_int(cconfs[OPT_COMPRESSION]),
			sb->compression /* from the manifest */, cconfs)))
		{
			logp("WARNING: librsync error when patching %s: %d\n",
				oldpath, lrs);
			cntr_add(get_cntr(cconfs[OPT_CNTR]), CMD_WARNING, 1);
			// Try to carry on with the rest of the backup
			// regardless.
			//ret=-1;
			// Remove anything that got written.
			unlink(newpath);
			unlink(infpath);
			free(infpath);

			// First, note that we want to remove this entry from
			// the manifest.
			if(!*delfp
			  && !(*delfp=open_file(fdirs->deletionsfile, "ab")))
			{
				// Could not mark this file as deleted. Fatal.
				goto end;
			}
			if(sbufl_to_manifest(sb, *delfp, NULL))
				goto end;
			if(fflush(*delfp))
			{
				logp("error fflushing deletions file in %s: %s\n", __func__, strerror(errno));
				goto end;
			}
	
			ret=0;
			goto end;
		}

		// Get rid of the inflated old file.
		unlink(infpath);
		free(infpath);

		// Need to generate a reverse diff, unless we are keeping a
		// hardlinked archive.
		if(!hardlinked_current)
		{
			if(gen_rev_delta(sigpath, deltabdir,
				oldpath, newpath, datapth, sb, cconfs))
					goto end;
		}

		// Power interruptions should be recoverable. If it happens
		// before this point, the data jiggle for this file has to be
		// done again.
		// Once finpath is in place, no more jiggle is required.

		// Use the fresh new file.
		// Rename race condition is of no consequence, because finpath
		// will just get recreated automatically.
		if(do_rename(newpath, finpath))
			goto end;

		// Remove the forward delta, as it is no longer needed. There
		// is a reverse diff and the finished finished file is in place.
		//logp("Deleting delta.forward...\n");
		unlink(deltafpath);

		// Remove the old file. If a power cut happens just before
		// this, the old file will hang around forever.
		// FIX THIS: maybe put in something to detect this.
		// ie, both a reverse delta and the old file exist.
		if(!hardlinked_current)
		{
			//logp("Deleting oldpath...\n");
			unlink(oldpath);
		}
	}
	else if(!lstat(newpath, &statp) && S_ISREG(statp.st_mode))
	{
		// Use the fresh new file.
		// This needs to happen after checking
		// for the forward delta, because the
		// patching stuff writes to newpath.

		// Rename race condition is of no consequence, because finpath
		// will just get recreated automatically.

		//logp("Using newly received file\n");
		if(do_rename(newpath, finpath))
			goto end;
	}
	else if(!lstat(oldpath, &statp) && S_ISREG(statp.st_mode))
	{
		// Use the old unchanged file.
		// Hard link it first.
		//logp("Hard linking to old file: %s\n", datapth);
		if(do_link(oldpath, finpath, &statp, cconfs,
		  0 /* do not overwrite finpath (should never need to) */))
			goto end;
		else
		{
			// If we are not keeping a hardlinked
			// archive, delete the old link.
			if(!hardlinked_current)
			{
				//logp("Unlinking old file: %s\n", oldpath);
				unlink(oldpath);
			}
		}
	}
	else
	{
		logp("could not find: %s\n", oldpath);
		goto end;
	}

	ret=0;
end:
	free_w(&oldpath);
	free_w(&newpath);
	free_w(&finpath);
	free_w(&deltafpath);
	return ret;
}
示例#25
0
文件: candidate.c 项目: vanElden/burp
void candidate_free_content(struct candidate *c)
{
	if(!c) return;
	free_w(&c->path);
}
示例#26
0
/* Need to make all the stuff that this does atomic so that existing backups
   never get broken, even if somebody turns the power off on the server. */ 
static int atomic_data_jiggle(struct sdirs *sdirs, struct fdirs *fdirs,
	int hardlinked_current, struct conf **cconfs, unsigned long bno)
{
	int ret=-1;
	char *datapth=NULL;
	char *tmpman=NULL;
	struct stat statp;

	char *deltabdir=NULL;
	char *deltafdir=NULL;
	char *sigpath=NULL;
	gzFile zp=NULL;
	struct sbuf *sb=NULL;

	FILE *delfp=NULL;

	logp("Doing the atomic data jiggle...\n");

	if(!(tmpman=get_tmp_filename(fdirs->manifest)))
		goto error;
	if(lstat(fdirs->manifest, &statp))
	{
		// Manifest does not exist - maybe the server was killed before
		// it could be renamed.
		logp("%s did not exist - trying %s\n", fdirs->manifest, tmpman);
		// Rename race condition is of no consequence, because manifest
		// already does not exist.
		do_rename(tmpman, fdirs->manifest);
	}
	if(!(zp=gzopen_file(fdirs->manifest, "rb")))
		goto error;

	if(!(deltabdir=prepend_s(fdirs->currentdup, "deltas.reverse"))
	  || !(deltafdir=prepend_s(sdirs->finishing, "deltas.forward"))
	  || !(sigpath=prepend_s(fdirs->currentdup, "sig.tmp"))
	  || !(sb=sbuf_alloc(cconfs)))
	{
		log_out_of_memory(__func__);
		goto error;
	}

	mkdir(fdirs->datadir, 0777);

	while(1)
	{
		switch(sbufl_fill(sb,
			NULL, NULL, zp, get_cntr(cconfs[OPT_CNTR])))
		{
			case 0: break;
			case 1: goto end;
			default: goto error;
		}
		if(sb->protocol1->datapth.buf)
		{
			if(write_status(CNTR_STATUS_SHUFFLING,
				sb->protocol1->datapth.buf, cconfs)
			  || jiggle(sdirs, fdirs, sb, hardlinked_current,
				deltabdir, deltafdir,
				sigpath, &delfp, cconfs))
					goto error;
		}
		sbuf_free_content(sb);
	}

end:
	if(close_fp(&delfp))
	{
		logp("error closing %s in atomic_data_jiggle\n",
			fdirs->deletionsfile);
		goto error;
	}

	if(maybe_delete_files_from_manifest(tmpman, fdirs, cconfs))
		goto error;

	// Remove the temporary data directory, we have probably removed
	// useful files from it.
	sync(); // try to help CIFS
	recursive_delete(deltafdir, NULL, 0 /* do not del files */);

	ret=0;
error:
	gzclose_fp(&zp);
	close_fp(&delfp);
	sbuf_free(&sb);
	free_w(&deltabdir);
	free_w(&deltafdir);
	free_w(&sigpath);
	free_w(&datapth);
	free_w(&tmpman);
	return ret;
}
示例#27
0
文件: bedup.c 项目: ZungBang/burp
static void file_free_content(struct file *file)
{
	if(!file) return;
	free_w(&file->path);
}
示例#28
0
文件: sdirs.c 项目: Sherlock221B/burp
void sdirs_free_content(struct sdirs *sdirs)
{
        free_w(&sdirs->base);
        free_w(&sdirs->dedup);
        free_w(&sdirs->champlock);
        free_w(&sdirs->champsock);
        free_w(&sdirs->champlog);
        free_w(&sdirs->data);
        free_w(&sdirs->clients);
        free_w(&sdirs->client);

        free_w(&sdirs->working);
        free_w(&sdirs->rworking);
        free_w(&sdirs->finishing);
        free_w(&sdirs->current);
        free_w(&sdirs->currenttmp);
        free_w(&sdirs->deleteme);

        free_w(&sdirs->timestamp);
        free_w(&sdirs->changed);
        free_w(&sdirs->unchanged);
	free_w(&sdirs->manifest);
	free_w(&sdirs->rmanifest);
        free_w(&sdirs->cmanifest);
	free_w(&sdirs->phase1data);

	free_w(&sdirs->lockdir);
	lock_free(&sdirs->lock);

	// Burp1 directories.
	free_w(&sdirs->currentdata);
	free_w(&sdirs->datadirtmp);
	free_w(&sdirs->phase2data);
	free_w(&sdirs->unchangeddata);
	free_w(&sdirs->cincexc);
	free_w(&sdirs->deltmppath);
	free_w(&sdirs->treepath);
}
示例#29
0
文件: bedup.c 项目: pkdevbox/burp
static int check_files(struct mystruct *find, struct file *newfile,
	struct stat *info, const char *ext, unsigned int maxlinks)
{
	int found=0;
	struct fzp *nfp=NULL;
	struct fzp *ofp=NULL;
	struct file *f=NULL;

	for(f=find->files; f; f=f->next)
	{
//printf("  against: '%s'\n", f->path);
		if(!f->path)
		{
			// If the full_match() function fails to open oldfile
			// (which could happen if burp deleted some old
			// directories), it will free path and set it to NULL.
			// Skip entries like this.
			continue;
		}
		if(newfile->dev!=f->dev)
		{
			// Different device.
			continue;
		}
		if(newfile->ino==f->ino)
		{
			// Same device, same inode, therefore these two files
			// are hardlinked to each other already.
			found++;
			break;
		}
		if((!newfile->part_cksum && get_part_cksum(newfile, &nfp))
		  || (!f->part_cksum && get_part_cksum(f, &ofp)))
		{
			// Some error with md5sums Give up.
			return -1;
		}
		if(newfile->part_cksum!=f->part_cksum)
		{
			fzp_close(&ofp);
			continue;
		}
		//printf("  %s, %s\n", find->files->path, newfile->path);
		//printf("  part cksum matched\n");

		if((!newfile->full_cksum && get_full_cksum(newfile, &nfp))
		  || (!f->full_cksum && get_full_cksum(f, &ofp)))
		{
			// Some error with md5sums Give up.
			return -1;
		}
		if(newfile->full_cksum!=f->full_cksum)
		{
			fzp_close(&ofp);
			continue;
		}

		//printf("  full cksum matched\n");
		if(!full_match(newfile, f, &nfp, &ofp))
		{
			fzp_close(&ofp);
			continue;
		}
		//printf("  full match\n");
		//printf("%s, %s\n", find->files->path, newfile->path);

		// If there are already enough links to this file, replace
		// our memory of it with the new file so that files later on
		// can link to the new one. 
		if(f->nlink>=maxlinks)
		{
			// Just need to reset the path name and the number
			// of links, and pretend that it was found otherwise
			// NULL newfile will get added to the memory.
			reset_old_file(f, newfile, info);
			found++;
			break;
		}

		found++;
		count++;

		if(verbose) printf("%s\n", newfile->path);

		// Now hardlink it.
		if(makelinks)
		{
			switch(do_hardlink(newfile, f, ext))
			{
				case 0:
					f->nlink++;
					// Only count bytes as saved if we
					// removed the last link.
					if(newfile->nlink==1)
						savedbytes+=info->st_size;
					break;
				case -1:
					// On error, replace the memory of the
					// old file with the one that we just
					// found. It might work better when
					// someone later tries to link to the
					// new one instead of the old one.
					reset_old_file(f, newfile, info);
					count--;
					break;
				default:
					// Abandon all hope.
					// This could happen if renaming the
					// hardlink failed in such a way that
					// the target file was unlinked without
					// being replaced - ie, if the max
					// number of hardlinks is being hit.
					return -1;
			}
		}
		else if(deletedups)
		{
			if(unlink(newfile->path))
			{
				logp("Could not delete %s: %s\n",
					newfile->path, strerror(errno));
			}
			else
			{
				// Only count bytes as saved if we removed the
				// last link.
				if(newfile->nlink==1)
					savedbytes+=info->st_size;
			}
		}
		else
		{
			// To be able to tell how many bytes
			// are saveable.
			savedbytes+=info->st_size;
		}

		break;
	}
	fzp_close(&nfp);
	fzp_close(&ofp);

	if(found)
	{
		free_w(&newfile->path);
		return 0;
	}

	if(add_file(find, newfile)) return -1;

	return 0;
}
示例#30
0
static int jiggle(struct sdirs *sdirs, struct fdirs *fdirs, struct sbuf *sb,
	int hardlinked_current, const char *deltabdir, const char *deltafdir,
	const char *sigpath, struct fzp **delfp, struct conf **cconfs)
{
	int ret=-1;
	struct stat statp;
	char *oldpath=NULL;
	char *newpath=NULL;
	char *finpath=NULL;
	char *deltafpath=NULL;
	const char *datapth=sb->protocol1->datapth.buf;

	// If the previous backup was a hardlinked_archive, there will not be
	// a currentdup directory - just directly use the file in the previous
	// backup.
	if(!(oldpath=prepend_s(hardlinked_current?
		sdirs->currentdata:fdirs->currentdupdata, datapth))
	  || !(newpath=prepend_s(fdirs->datadirtmp, datapth))
	  || !(finpath=prepend_s(fdirs->datadir, datapth))
	  || !(deltafpath=prepend_s(deltafdir, datapth)))
		goto end;

	if(!lstat(finpath, &statp) && S_ISREG(statp.st_mode))
	{
		// Looks like an interrupted jiggle did this file already.
		static int donemsg=0;
		if(!unlink(deltafpath))
			logp("deleted unneeded forward delta: %s\n",
				deltafpath);
		if(!donemsg)
		{
			logp("skipping already present file: %s\n", finpath);
			logp("to save log space, skips of other already present files will not be logged\n");
			donemsg++;
		}
		ret=0;
		goto end;
	}

	if(mkpath(&finpath, fdirs->datadir))
	{
		logp("could not create path for: %s\n", finpath);
		goto end;
	}

	if(!lstat(deltafpath, &statp) && S_ISREG(statp.st_mode))
	{
		if(mkpath(&newpath, fdirs->datadirtmp))
		{
			logp("could not create path for: %s\n", newpath);
			goto end;
		}
		ret=forward_patch_and_reverse_diff(
			fdirs,
			delfp,
			deltabdir,
			deltafdir,
			deltafpath,
			sigpath,
			oldpath,
			newpath,
			datapth,
			finpath,
			hardlinked_current,
			sb,
			cconfs
		);
		goto end;
	}

	if(!lstat(newpath, &statp) && S_ISREG(statp.st_mode))
	{
		// Use the fresh new file.
		// This needs to happen after checking
		// for the forward delta, because the
		// patching stuff writes to newpath.

		// Rename race condition is of no consequence, because finpath
		// will just get recreated automatically.

		//logp("Using newly received file\n");
		ret=do_rename(newpath, finpath);
		goto end;
	}

	if(!lstat(oldpath, &statp) && S_ISREG(statp.st_mode))
	{
		// Use the old unchanged file.
		// Hard link it first.
		//logp("Hard linking to old file: %s\n", datapth);
		if(do_link(oldpath, finpath, &statp, cconfs,
		  0 /* do not overwrite finpath (should never need to) */))
			goto end;
		else
		{
			// If we are not keeping a hardlinked
			// archive, delete the old link.
			if(!hardlinked_current)
			{
				//logp("Unlinking old file: %s\n", oldpath);
				unlink(oldpath);
			}
		}
		ret=0;
		goto end;
	}

	logp("could not find: %s\n", oldpath);
end:
	free_w(&oldpath);
	free_w(&newpath);
	free_w(&finpath);
	free_w(&deltafpath);
	return ret;
}