std::wstring ChangeJournalWatcher::getFilename(_i64 frn, _i64 rid)
{
	std::wstring path;
	_i64 curr_id=frn;
	while(true)
	{
		q_get_name->Bind(curr_id);
		q_get_name->Bind(rid);
		db_results res=q_get_name->Read();
		q_get_name->Reset();

		if(!res.empty())
		{
			_i64 pid=os_atoi64(wnarrow(res[0][L"pid"]));
			if(pid!=-1)
			{
				path=res[0][L"name"]+os_file_sep()+path;
				curr_id=pid;
			}
			else
			{
				path=res[0][L"name"]+os_file_sep()+path;
				break;
			}
		}
		else
		{
			Server->Log(L"Couldn't follow up to root. Current path: "+path, LL_ERROR);
			return L"";
		}
	}
	return path;
}
示例#2
0
void saveGeneralSettings(str_map &GET, IDatabase *db)
{
	IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid=0 AND key=?");
	IQuery *q_update=db->Prepare("UPDATE settings_db.settings SET value=? WHERE key=? AND clientid=0");
	IQuery *q_insert=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES (?,?,0)");

	std::vector<std::wstring> settings=getGlobalSettingsList();
	for(size_t i=0;i<settings.size();++i)
	{
		str_map::iterator it=GET.find(settings[i]);
		if(it!=GET.end())
		{
			updateSetting(settings[i], it->second, q_get, q_update, q_insert);
		}
	}

#ifdef _WIN32
	std::wstring tmpdir=GET[L"tmpdir"];
	if(!tmpdir.empty())
	{
		os_create_dir(tmpdir+os_file_sep()+L"urbackup_tmp");
		Server->setTemporaryDirectory(tmpdir+os_file_sep()+L"urbackup_tmp");
	}
#endif
}
示例#3
0
bool CopyFolder(std::wstring src, std::wstring dst)
{
	if(!os_create_dir(dst))
		return false;

	std::vector<SFile> curr_files=getFiles(src);
	for(size_t i=0;i<curr_files.size();++i)
	{
		if(curr_files[i].isdir)
		{
			bool b=CopyFolder(src+os_file_sep()+curr_files[i].name, dst+os_file_sep()+curr_files[i].name);
			if(!b)
				return false;
		}
		else
		{
			if(!os_create_hardlink(dst+os_file_sep()+curr_files[i].name, src+os_file_sep()+curr_files[i].name, false, NULL) )
			{
				BOOL b=CopyFileW( (src+os_file_sep()+curr_files[i].name).c_str(), (dst+os_file_sep()+curr_files[i].name).c_str(), FALSE);
				if(!b)
				{
					return false;
				}
			}
		}
	}

	return true;
}
void ChangeJournalWatcher::indexRootDirs(_i64 rid, const std::wstring &root, _i64 parent)
{
	if(indexing_in_progress)
	{
		if(Server->getTimeMS()-last_index_update>10000)
		{
			update();
			last_index_update=Server->getTimeMS();
		}
	}

	std::wstring dir=root+os_file_sep();
	HANDLE hDir;
	if(root.size()==2)
		hDir=CreateFileW(dir.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
	else
		hDir=CreateFileW(root.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

	if(INVALID_HANDLE_VALUE==hDir)
		return;
	BY_HANDLE_FILE_INFORMATION fi;
	GetFileInformationByHandle(hDir, &fi);
	CloseHandle(hDir);
	LARGE_INTEGER frn;
	frn.LowPart=fi.nFileIndexLow;
	frn.HighPart=fi.nFileIndexHigh;

	addFrn(ExtractFileName(root)+os_file_sep(), parent, frn.QuadPart, rid);

	std::vector<SFile> files=getFiles(root);
	for(size_t i=0;i<files.size();++i)
	{
		if(files[i].isdir)
		{
			indexRootDirs(rid, dir+files[i].name, frn.QuadPart);
		}
	}
}
示例#5
0
int zfs_test()
{
	std::cout << "Testing for zfs..." << std::endl;
				
	if(getBackupfolderPath(mode_zfs).empty())
	{
		std::cout << "TEST FAILED: Dataset is not set via /etc/urbackup/dataset" << std::endl;
		return 1;
	}
	
	std::string clientdir=getBackupfolderPath(mode_zfs)+os_file_sep()+"testA54hj5luZtlorr494";
	
	if(create_subvolume(mode_zfs, clientdir)
		&& remove_subvolume(mode_zfs, clientdir) )
	{
		std::cout << "ZFS TEST OK" << std::endl;
		
		clientdir=getBackupfolderPath(mode_zfs_file)+os_file_sep()+"testA54hj5luZtlorr494";
		
		if(getBackupfolderPath(mode_zfs_file).empty())
		{
			return 10 + mode_zfs;
		}
		else if(create_subvolume(mode_zfs, clientdir)
			&& remove_subvolume(mode_zfs, clientdir))
		{
			return 10 + mode_zfs_file;
		}
	
		return 10 + mode_zfs;
	}
	else
	{
		std::cout << "TEST FAILED: Creating test zfs volume \"" << clientdir << "\" failed" << std::endl;
	}
	return 1;
}
示例#6
0
void BackupServer::operator()(void)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(),URBACKUPDB_SERVER);
	ISettingsReader *settings=Server->createDBSettingsReader(Server->getDatabase(Server->getThreadID(),URBACKUPDB_SERVER), "settings_db.settings");

#ifdef _WIN32
	std::wstring tmpdir;
	if(settings->getValue(L"tmpdir", &tmpdir) && !tmpdir.empty())
	{
		os_remove_nonempty_dir(tmpdir+os_file_sep()+L"urbackup_tmp");
		if(!os_create_dir(tmpdir+os_file_sep()+L"urbackup_tmp"))
		{
			Server->wait(5000);
			os_create_dir(tmpdir+os_file_sep()+L"urbackup_tmp");
		}
		Server->setTemporaryDirectory(tmpdir+os_file_sep()+L"urbackup_tmp");
	}
	else
	{
		wchar_t tmpp[MAX_PATH];
		DWORD l;
		if((l=GetTempPathW(MAX_PATH, tmpp))==0 || l>MAX_PATH )
		{
			wcscpy_s(tmpp,L"C:\\");
		}

		std::wstring w_tmp=tmpp;

		if(!w_tmp.empty() && w_tmp[w_tmp.size()-1]=='\\')
		{
			w_tmp.erase(w_tmp.size()-1, 1);		}


		os_remove_nonempty_dir(w_tmp+os_file_sep()+L"urbackup_tmp");
		if(!os_create_dir(w_tmp+os_file_sep()+L"urbackup_tmp"))
		{
			Server->wait(5000);
			os_create_dir(tmpdir+os_file_sep()+L"urbackup_tmp");
		}
		Server->setTemporaryDirectory(w_tmp+os_file_sep()+L"urbackup_tmp");
	}
#endif
	if( settings->getValue("use_tmpfiles", "")!="true" )
	{
		std::wstring backupfolder;
		if( settings->getValue(L"backupfolder", &backupfolder) )
		{
			std::wstring tmpfile_path=backupfolder+os_file_sep()+L"urbackup_tmp_files";

			Server->Log("Removing temporary files...");
			os_remove_nonempty_dir(tmpfile_path);
			Server->Log("Recreating temporary folder...");
			if(!os_create_dir(tmpfile_path))
			{
				Server->wait(5000);
				os_create_dir(tmpfile_path);
			}
		}
	}

	testSnapshotAvailability(db);

	q_get_extra_hostnames=db->Prepare("SELECT id,hostname FROM settings_db.extra_clients");
	q_update_extra_ip=db->Prepare("UPDATE settings_db.extra_clients SET lastip=? WHERE id=?");

	FileClient fc;

	Server->wait(1000);

	while(true)
	{
		findClients(fc);
		startClients(fc);

		if(!ServerStatus::isActive() && settings->getValue("autoshutdown", "false")=="true")
		{
			writestring("true", "urbackup/shutdown_now");
#ifdef _WIN32
			ExitWindowsEx(EWX_POWEROFF|EWX_FORCEIFHUNG, SHTDN_REASON_MAJOR_APPLICATION|SHTDN_REASON_MINOR_OTHER );
#endif
		}

		std::string r;
		exitpipe->Read(&r, 20000);
		if(r=="exit")
		{
			removeAllClients();
			exitpipe->Write("ok");
			Server->destroy(settings);
			db->destroyAllQueries();
			delete this;
			return;
		}
	}
}
示例#7
0
void FSNTFSWIN::logFileChangesInt(const std::string& volpath, int64 min_size, char* fc_bitmap, int64& total_files, int64& total_changed_sectors)
{
	std::vector<SFile> files = getFiles(volpath);

	for (size_t i = 0; i < files.size(); ++i)
	{
		if (files[i].isdir)
		{
			if (!files[i].issym)
			{
				logFileChangesInt(volpath + os_file_sep() + files[i].name, min_size, fc_bitmap, total_files, total_changed_sectors);
			}
		}
		else if(!files[i].issym)
		{
			HANDLE hFile = CreateFileW(Server->ConvertToWchar(os_file_prefix(volpath + os_file_sep() + files[i].name)).c_str(), GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
				OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

			if (hFile != INVALID_HANDLE_VALUE)
			{
				int64 sector_count = 0;
				int64 total_sectors = 0;

				STARTING_VCN_INPUT_BUFFER start_vcn = {};
				std::vector<char> ret_buf;
				ret_buf.resize(32768);

				while (true)
				{
					RETRIEVAL_POINTERS_BUFFER* ret_ptrs = reinterpret_cast<RETRIEVAL_POINTERS_BUFFER*>(ret_buf.data());

					DWORD bytesRet = 0;

					BOOL b = DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS,
						&start_vcn, sizeof(start_vcn), ret_ptrs, static_cast<DWORD>(ret_buf.size()), &bytesRet, NULL);

					DWORD err = GetLastError();

					if (b || err == ERROR_MORE_DATA)
					{
						LARGE_INTEGER last_vcn = ret_ptrs->StartingVcn;
						for (DWORD i = 0; i<ret_ptrs->ExtentCount; ++i)
						{
							if (ret_ptrs->Extents[i].Lcn.QuadPart != -1)
							{
								int64 count = ret_ptrs->Extents[i].NextVcn.QuadPart - last_vcn.QuadPart;

								sector_count += countSectors(ret_ptrs->Extents[i].Lcn.QuadPart, count, fc_bitmap);
								total_sectors += count;
							}

							last_vcn = ret_ptrs->Extents[i].NextVcn;
						}
					}

					if (!b)
					{
						if (err == ERROR_MORE_DATA)
						{
							start_vcn.StartingVcn = ret_ptrs->Extents[ret_ptrs->ExtentCount - 1].NextVcn;
						}
						else if (err == ERROR_HANDLE_EOF)
						{
							CloseHandle(hFile);
							break;
						}
						else
						{
							Server->Log("Error " + convert((int)GetLastError()) + " while accessing retrieval points", LL_WARNING);
							CloseHandle(hFile);
							break;
						}
					}
					else
					{
						CloseHandle(hFile);
						break;
					}
				}

				if (sector_count > 0)
				{
					++total_files;
					total_changed_sectors += sector_count;
				}
				
				if (sector_count > 0
					&& sector_count*getBlocksize()>min_size)
				{
					Server->Log("Changed in " + volpath + os_file_sep() + files[i].name + ": " + convert(sector_count) + "/"+convert(total_sectors)+" sectors " + PrettyPrintBytes(sector_count*getBlocksize())
						+"/"+ PrettyPrintBytes(total_sectors*getBlocksize()), LL_INFO);
				}
			}
			else
			{
				Server->Log("Error opening file: " + volpath + os_file_sep() + files[i].name, LL_INFO);
			}
		}
	}
}
std::vector<SFile> getFilesWin(const std::string &path, bool *has_error,
	bool exact_filesize, bool with_usn, bool ignore_other_fs)
{
	if(has_error!=NULL)
	{
		*has_error=false;
	}

	std::vector<char> usn_buffer;
	usn_buffer.resize(1024);

	std::vector<SFile> tmp;
	HANDLE fHandle;
	WIN32_FIND_DATAW wfd;
	std::wstring tpath=ConvertToWchar(path);
	if(!tpath.empty() && tpath[tpath.size()-1]=='\\' ) tpath.erase(tpath.size()-1, 1);
	fHandle=FindFirstFileW((tpath+L"\\*").c_str(),&wfd); 
	if(fHandle==INVALID_HANDLE_VALUE)
	{
		if(tpath.find(L"\\\\?\\UNC")==0)
		{
			tpath.erase(0, 7);
			tpath=L"\\"+tpath;
			fHandle=FindFirstFileW((tpath+L"\\*").c_str(),&wfd); 
		}
		else if(tpath.find(L"\\\\?\\")==0)
		{
			tpath.erase(0, 4);
			fHandle=FindFirstFileW((tpath+L"\\*").c_str(),&wfd); 
		}
		if(fHandle==INVALID_HANDLE_VALUE)
		{
			if(has_error!=NULL)
			{
				*has_error=true;
			}
			return tmp;
		}
	}

	do
	{
		SFile f;
		f.name=ConvertFromWchar(wfd.cFileName);
		if(f.name=="." || f.name==".." )
			continue;

		f.usn=0;
		f.isdir=(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)>0;			
		LARGE_INTEGER lwt;
		lwt.HighPart=wfd.ftLastWriteTime.dwHighDateTime;
		lwt.LowPart=wfd.ftLastWriteTime.dwLowDateTime;
		f.last_modified=os_windows_to_unix_time(lwt.QuadPart);
		LARGE_INTEGER size;
		size.HighPart=wfd.nFileSizeHigh;
		size.LowPart=wfd.nFileSizeLow;
		f.size=size.QuadPart;

		lwt.HighPart=wfd.ftCreationTime.dwHighDateTime;
		lwt.LowPart=wfd.ftCreationTime.dwLowDateTime;
		f.created=os_windows_to_unix_time(lwt.QuadPart);

		std::string reparse_target;
		if (ignore_other_fs
			&& wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
			&& wfd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT
			&& os_get_symlink_target(os_file_prefix(path + os_file_sep() + f.name), reparse_target)
			&& is_volume(reparse_target) )
		{
			continue;
		}
		else if(wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
			&& (wfd.dwReserved0== IO_REPARSE_TAG_SYMLINK
				|| wfd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) )
		{
			f.issym=true;
			f.isspecialf=true;
		}
		else if (wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
			&& (wfd.dwReserved0 == 0x8000001b /*IO_REPARSE_TAG_APPEXECLINK*/ ))
		{
			f.isspecialf = true;
		}

		f.isencrypted = (wfd.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED)>0;

		if( (exact_filesize 
			&& !f.isdir
			&& !f.issym ) || with_usn )
		{
			if(with_usn)
			{
				HANDLE hFile = CreateFileW(os_file_prefix(tpath+L"\\"+ConvertToWchar(f.name)).c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,
					OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);

				if(hFile!=INVALID_HANDLE_VALUE)
				{
					if (exact_filesize
						&& !f.isdir && !f.issym)
					{
						BY_HANDLE_FILE_INFORMATION fileInformation;
						if (GetFileInformationByHandle(hFile, &fileInformation)!=0)
						{
							LARGE_INTEGER fsize;
							fsize.LowPart = fileInformation.nFileSizeLow;
							fsize.HighPart = fileInformation.nFileSizeHigh;
							f.size = fsize.QuadPart;

							f.nlinks = fileInformation.nNumberOfLinks;
						}
					}

					
					DWORD last_err=0;
					do 
					{
						DWORD ret_bytes = 0;
						BOOL b = DeviceIoControl(hFile, FSCTL_READ_FILE_USN_DATA, NULL, 0,
							usn_buffer.data(), static_cast<DWORD>(usn_buffer.size()), &ret_bytes, NULL);

						if(b)
						{
							USN_RECORD* usnv2=reinterpret_cast<USN_RECORD*>(usn_buffer.data());
							if(usnv2->MajorVersion==2)
							{
								f.usn = usnv2->Usn;
							}
							else if(usnv2->MajorVersion==3)
							{
								usn::USN_RECORD_V3* usnv3=reinterpret_cast<usn::USN_RECORD_V3*>(usn_buffer.data());
								f.usn = usnv3->Usn;
							}
							else
							{
								Log("USN entry major version "+convert(usnv2->MajorVersion)+" of file \""+ConvertFromWchar(tpath)+"\\"+f.name+"\" not supported", LL_ERROR);
							}
						}
						else
						{
							last_err=GetLastError();
						}

						if(last_err==ERROR_INSUFFICIENT_BUFFER)
						{
							usn_buffer.resize(usn_buffer.size()*2);
						}

					} while (last_err==ERROR_INSUFFICIENT_BUFFER);

					CloseHandle(hFile);
				}
			}
			else
			{
				WIN32_FILE_ATTRIBUTE_DATA fad;
				if( GetFileAttributesExW(os_file_prefix(tpath+L"\\"+ConvertToWchar(f.name)).c_str(),  GetFileExInfoStandard, &fad) )
				{
					size.HighPart = fad.nFileSizeHigh;
					size.LowPart = fad.nFileSizeLow;
					f.size = size.QuadPart;

					lwt.HighPart = fad.ftLastWriteTime.dwHighDateTime;
					lwt.LowPart = fad.ftLastWriteTime.dwLowDateTime;

					f.last_modified = os_windows_to_unix_time(lwt.QuadPart);

					lwt.HighPart=fad.ftCreationTime.dwHighDateTime;
					lwt.LowPart=fad.ftCreationTime.dwLowDateTime;

					f.created=os_windows_to_unix_time(lwt.QuadPart);
				}
			}							
		}
		if(f.last_modified<0) f.last_modified*=-1;
		tmp.push_back(f);		
	}
	while (FindNextFileW(fHandle,&wfd) );

	if (GetLastError() != ERROR_NO_MORE_FILES)
	{
		DWORD err = GetLastError();
		if (has_error != NULL)
		{
			*has_error = true;
		}

		FindClose(fHandle);

		std::sort(tmp.begin(), tmp.end());

		SetLastError(err);

		return tmp;
	}

	FindClose(fHandle);

	std::sort(tmp.begin(), tmp.end());

	return tmp;
}
bool os_sync(const std::string & path)
{
	std::string prefixedbpath = os_file_prefix(path);

	if (next(prefixedbpath, 0, "\\\\?\\UNC"))
	{
		HANDLE hVol = CreateFileW(ConvertToWchar(prefixedbpath).c_str(),
			GENERIC_READ | GENERIC_WRITE,
			FILE_SHARE_WRITE | FILE_SHARE_READ,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL,
			NULL);

		if (hVol == INVALID_HANDLE_VALUE)
		{
			return false;
		}

		BOOL b = FlushFileBuffers(hVol);

		CloseHandle(hVol);

		return b == TRUE;
	}

	std::wstring tvolume;
	tvolume.resize(prefixedbpath.size() + 100);
	DWORD cchBufferLength = static_cast<DWORD>(tvolume.size());
	BOOL b = GetVolumePathNameW(ConvertToWchar(prefixedbpath).c_str(), &tvolume[0], cchBufferLength);
	if (!b)
	{
		return false;
	}

	std::string volume = ConvertFromWchar(tvolume.c_str());

	if (volume.find("\\\\?\\") == 0
		&& volume.find("\\\\?\\GLOBALROOT") != 0)
	{
		volume.erase(0, 4);
	}

	if (!volume.empty()
		&& volume[volume.size() - 1] == os_file_sep()[0])
	{
		volume = volume.substr(0, volume.size() - 1);
	}

	HANDLE hVol = CreateFileW(ConvertToWchar("\\\\.\\"+volume).c_str(),
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_WRITE | FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hVol == INVALID_HANDLE_VALUE)
	{
		return false;
	}

	b = FlushFileBuffers(hVol);

	CloseHandle(hVol);
	
	return b == TRUE;
}
void ChangeJournalWatcher::indexRootDirs2(const std::wstring &root, SChangeJournal *sj)
{
	db->Write("CREATE TEMPORARY TABLE map_frn_tmp (name TEXT, pid INTEGER, frn INTEGER, rid INTEGER)");
	q_add_frn_tmp=db->Prepare("INSERT INTO map_frn_tmp (name, pid, frn, rid) VALUES (?, ?, ?, ?)", false);

	HANDLE hDir = CreateFile((root+os_file_sep()).c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE,	NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

	if(hDir==INVALID_HANDLE_VALUE)
	{
		Server->Log("Could not open root HANDLE.", LL_ERROR);
		return;
	}

	BY_HANDLE_FILE_INFORMATION fi;
	GetFileInformationByHandle(hDir, &fi);
	CloseHandle(hDir);
	LARGE_INTEGER frn;
	frn.LowPart=fi.nFileIndexLow;
	frn.HighPart=fi.nFileIndexHigh;

	addFrn(root, -1, frn.QuadPart, sj->rid);

	MFT_ENUM_DATA med;
	med.StartFileReferenceNumber = 0;
	med.LowUsn = 0;
	med.HighUsn = MAXLONGLONG; //sj->last_record;

	// Process MFT in 64k chunks
	BYTE *pData=new BYTE[sizeof(DWORDLONG) + 0x10000];
	DWORDLONG fnLast = 0;
	DWORD cb;
	while (DeviceIoControl(sj->hVolume, FSCTL_ENUM_USN_DATA, &med, sizeof(med),pData, sizeof(DWORDLONG) + 0x10000, &cb, NULL) != FALSE)
	{
		if(indexing_in_progress)
		{
			if(Server->getTimeMS()-last_index_update>10000)
			{
				update(false, sj->vol_str);
				last_index_update=Server->getTimeMS();
			}
		}

		if(dwt->is_stopped())
		{
			Server->Log("Stopped indexing process", LL_WARNING);
			break;
		}

		PUSN_RECORD pRecord = (PUSN_RECORD) &pData[sizeof(USN)];
		while ((PBYTE) pRecord < (pData + cb))
		{
			if((pRecord->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0)
			{
				std::wstring filename;
				filename.resize(pRecord->FileNameLength / sizeof(wchar_t) );
				memcpy(&filename[0], (PBYTE) pRecord + pRecord->FileNameOffset, pRecord->FileNameLength);
				addFrnTmp(filename, pRecord->ParentFileReferenceNumber, pRecord->FileReferenceNumber, sj->rid);
			}
			pRecord = (PUSN_RECORD) ((PBYTE) pRecord + pRecord->RecordLength);
		}
		med.StartFileReferenceNumber = * (DWORDLONG *) pData;
	}

	delete []pData;
	db->destroyQuery(q_add_frn_tmp);
	q_add_frn_tmp=NULL;
	db->Write("INSERT INTO map_frn (name, pid, frn, rid) SELECT name, pid, frn, rid FROM map_frn_tmp");
	db->Write("DROP TABLE map_frn_tmp");

	update(true, sj->vol_str);
}
示例#11
0
int main(int argc, char *argv[])
{
	if(argc<2)
	{
		std::cout << "Not enough parameters" << std::endl;
		return 1;
	}
	
	std::string cmd;
	int mode = 0;
	if((std::string)argv[1]!="test")
	{
		if(argc<3)
		{
			std::cout << "Not enough parameters" << std::endl;
			return 1;
		}
		cmd=argv[2];
		mode=atoi(argv[1]);
	}
	else
	{
		cmd=argv[1];
	}

	std::string backupfolder=getBackupfolderPath(mode);
	
	if(backupfolder.empty())
	{	
		if(mode==mode_btrfs)
		{
			std::cout << "Backupfolder not set" << std::endl;
		}
		else if(mode==mode_zfs)
		{
			std::cout << "ZFS image dataset not set" << std::endl;
		}
		else if(mode==mode_zfs_file)
		{
			std::cout << "ZFS file dataset not set" << std::endl;
		}
		else
		{
			std::cout << "Unknown mode: " << mode << std::endl;
		}
		return 1;
	}
	
	if(cmd!="test" && mode==mode_zfs_file)
	{
		mode=mode_zfs;
	}
	
#ifndef _WIN32
	if(seteuid(0)!=0)
	{
		std::cout << "Cannot become root user" << std::endl;
		return 1;
	}
#endif

	if(cmd=="create")
	{
		if(argc<5)
		{
			std::cout << "Not enough parameters for create" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[3]);
		std::string name=handleFilename(argv[4]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;
		
		return create_subvolume(mode, subvolume_folder)?0:1;
	}
	else if(cmd=="mountpoint")
	{
		if(argc<5)
		{
			std::cout << "Not enough parameters for mountpoint" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[3]);
		std::string name=handleFilename(argv[4]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;
		
		return get_mountpoint(mode, subvolume_folder)?0:1;
	}
	else if(cmd=="snapshot")
	{
		if(argc<6)
		{
			std::cout << "Not enough parameters for snapshot" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[3]);
		std::string src_name=handleFilename(argv[4]);
		std::string dst_name=handleFilename(argv[5]);

		std::string subvolume_src_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+src_name;
		std::string subvolume_dst_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+dst_name;

		return create_snapshot(mode, subvolume_src_folder, subvolume_dst_folder)?0:1;
	}
	else if(cmd=="remove")
	{
		if(argc<5)
		{
			std::cout << "Not enough parameters for remove" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[3]);
		std::string name=handleFilename(argv[4]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;
		
		return remove_subvolume(mode, subvolume_folder)?0:1;
	}
	else if(cmd=="test")
	{
		std::cout << "Testing for btrfs..." << std::endl;
		std::string clientdir=backupfolder+os_file_sep()+"testA54hj5luZtlorr494";
		
		bool create_dir_rc=os_create_dir(clientdir);
		if(!create_dir_rc)
		{	
			remove_subvolume(mode_zfs, clientdir, true);
			remove_subvolume(mode_btrfs, clientdir+os_file_sep()+"A", true);
			remove_subvolume(mode_btrfs, clientdir+os_file_sep()+"B", true);
			os_remove_dir(clientdir);
		}
		create_dir_rc = create_dir_rc || os_create_dir(clientdir);
		if(create_dir_rc)
		{	
			if(!create_subvolume(mode_btrfs, clientdir+os_file_sep()+"A") )
			{
				std::cout << "TEST FAILED: Creating test btrfs subvolume failed" << std::endl;
				os_remove_dir(clientdir);
				
				return zfs_test();
			}
			
			bool suc=true;

			if(!create_snapshot(mode_btrfs, clientdir+os_file_sep()+"A", clientdir+os_file_sep()+"B") )
			{
				std::cout << "TEST FAILED: Creating test snapshot failed" << std::endl;
				suc=false;
			}
			
			if(suc)
			{			
				writestring("test", clientdir+os_file_sep()+"A"+os_file_sep()+"test");
				
				if(!os_create_hardlink(clientdir+os_file_sep()+"B"+os_file_sep()+"test", clientdir+os_file_sep()+"A"+os_file_sep()+"test", true, NULL))
				{
					std::cout << "TEST FAILED: Creating cross sub-volume reflink failed. Need Linux kernel >= 3.6." << std::endl;
					suc=false;
				}
				else
				{
					if(getFile(clientdir+os_file_sep()+"B"+os_file_sep()+"test")!="test")
					{
						std::cout << "TEST FAILED: Cannot read reflinked file" << std::endl;
						suc=false;
					}
				}
			}

			if(!remove_subvolume(mode_btrfs, clientdir+os_file_sep()+"A") )
			{
				std::cout << "TEST FAILED: Removing subvolume A failed" << std::endl;
				suc=false;
			}

			if(!remove_subvolume(mode_btrfs, clientdir+os_file_sep()+"B") )
			{
				std::cout << "TEST FAILED: Removing subvolume B failed" << std::endl;
				suc=false;
			}

			if(!os_remove_dir(clientdir))
			{
				std::cout << "TEST FAILED: Removing test clientdir failed" << std::endl;
				return 1;
			}
			
			if(!suc)
			{
				return 1;
			}
		}
		else
		{
			std::cout << "TEST FAILED: Creating test clientdir \"" << clientdir << "\" failed" << std::endl;
						
			return zfs_test();
		}
		std::cout << "BTRFS TEST OK" << std::endl;
		return 10 + mode_btrfs;
	}
	else if(cmd=="issubvolume")
	{
		if(argc<5)
		{
			std::cout << "Not enough parameters for issubvolume" << std::endl;
			return 1;
		}

		std::string clientname=handleFilename(argv[3]);
		std::string name=handleFilename(argv[4]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;
		
		return is_subvolume(mode, subvolume_folder)?0:1;
	}
	else if(cmd=="makereadonly")
	{
		if(argc<5)
		{
			std::cout << "Not enough parameters for makereadonly" << std::endl;
			return 1;
		}
		
		std::string clientname=handleFilename(argv[3]);
		std::string name=handleFilename(argv[4]);

		std::string subvolume_folder=backupfolder+os_file_sep()+clientname+os_file_sep()+name;
		
		return make_readonly(mode, subvolume_folder)?0:1;
	}
	else
	{
		std::cout << "Command not found" << std::endl;
		return 1;
	}
}