bool os_link_symbolic_junctions(const std::wstring &target, const std::wstring &lname)
{
	bool ret=false;
	std::wstring wtarget=target;
	HANDLE hJunc=INVALID_HANDLE_VALUE;
	char *buf=NULL;

	if(wtarget.find(os_file_prefix(L""))==0)
		wtarget.erase(0, os_file_prefix(L"").size());
	if(!wtarget.empty() && wtarget[0]!='\\')
		wtarget=L"\\??\\"+wtarget;
	if(!wtarget.empty() && wtarget[target.size()-1]!='\\')
		wtarget+=L"\\";

	if(!CreateDirectoryW(lname.c_str(), NULL) )
	{
		goto cleanup;
	}

	hJunc=CreateFileW(lname.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);
	if(hJunc==INVALID_HANDLE_VALUE)
		goto cleanup;

	size_t bsize=sizeof(REPARSE_MOUNTPOINT_DATA_BUFFER) + (wtarget.size()+1) * sizeof(wchar_t)+30;
	buf=new char[bsize];
	memset(buf, 0, bsize);

	REPARSE_MOUNTPOINT_DATA_BUFFER *rb=(REPARSE_MOUNTPOINT_DATA_BUFFER*)buf;
	rb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT;
	rb->ReparseTargetMaximumLength=(WORD)((wtarget.size()+1)*sizeof(wchar_t));
	rb->ReparseTargetLength=rb->ReparseTargetMaximumLength-1*sizeof(wchar_t);
	rb->ReparseDataLength=rb->ReparseTargetLength+12;
	memcpy(rb->ReparseTarget, wtarget.c_str(), rb->ReparseTargetMaximumLength);

	DWORD bytes_ret;
	if(!DeviceIoControl(hJunc, FSCTL_SET_REPARSE_POINT, rb, rb->ReparseDataLength+REPARSE_MOUNTPOINT_HEADER_SIZE, NULL, 0, &bytes_ret, NULL) )
	{
		goto cleanup;
	}
	ret=true;

cleanup:
	if(!ret)
	{
		#ifndef OS_FUNC_NO_SERVER
		Server->Log("Creating junction failed. Last error="+nconvert((int)GetLastError()), LL_ERROR);
		#endif
	}
	delete []buf;
	if(hJunc!=INVALID_HANDLE_VALUE)
		CloseHandle(hJunc);
	if(!ret)
	{
		RemoveDirectoryW(lname.c_str());
	}
	return ret;
}
Exemplo n.º 2
0
bool os_link_symbolic_junctions(const std::string &target, const std::string &lname, void* transaction)
{
	std::string wtarget = target;

	if (wtarget.find("\\\\?\\UNC") == 0)
	{
		wtarget.erase(0, 7);
		wtarget = "\\" + wtarget;
	}
	else if (wtarget.find(os_file_prefix("")) == 0)
	{
		wtarget.erase(0, os_file_prefix("").size());
	}

	if (!wtarget.empty() && wtarget[0] != '\\')
		wtarget = "\\??\\" + wtarget;

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

	return os_link_symbolic_junctions_raw(wtarget, lname, transaction);
}
Exemplo n.º 3
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);
			}
		}
	}
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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 BackupServerPrepareHash::operator()(void)
{
	while(true)
	{
		working=false;
		std::string data;
		size_t rc=pipe->Read(&data);
		if(data=="exitnow")
		{
			output->Write("exitnow");
			std::string t;
			exitpipe_hash->Read(&t);
			Server->destroy(exitpipe_hash);
			exitpipe->Write("ok");
			Server->Log("server_prepare_hash Thread finished");
			delete this;
			return;
		}
		else if(data=="exit")
		{
			output->Write("exit");
			Server->destroy(exitpipe);
			Server->Log("server_prepare_hash Thread finished");
			delete this;
			return;
		}
		else if(data=="flush")
		{
			continue;
		}

		if(rc>0)
		{
			working=true;
			
			CRData rd(&data);

			std::string temp_fn;
			rd.getStr(&temp_fn);

			int backupid;
			rd.getInt(&backupid);

			char incremental;
			rd.getChar(&incremental);

			std::string tfn;
			rd.getStr(&tfn);

			std::string hashpath;
			rd.getStr(&hashpath);

			std::string hashoutput_fn;
			rd.getStr(&hashoutput_fn);

			bool diff_file=!hashoutput_fn.empty();

			std::string old_file_fn;
			rd.getStr(&old_file_fn);

			IFile *tf=Server->openFile(os_file_prefix(Server->ConvertToUnicode(temp_fn)), MODE_READ);
			IFile *old_file=NULL;
			if(diff_file)
			{
				old_file=Server->openFile(os_file_prefix(Server->ConvertToUnicode(old_file_fn)), MODE_READ);
				if(old_file==NULL)
				{
					ServerLogger::Log(clientid, "Error opening file \""+old_file_fn+"\" from pipe for reading. File: old_file", LL_ERROR);
					if(tf!=NULL) Server->destroy(tf);
					continue;
				}
			}

			if(tf==NULL)
			{
				ServerLogger::Log(clientid, "Error opening file \""+temp_fn+"\" from pipe for reading file. File: temp_fn", LL_ERROR);
				has_error=true;
				if(old_file!=NULL)
				{
					Server->destroy(old_file);
				}
			}
			else
			{
				ServerLogger::Log(clientid, "PT: Hashing file \""+ExtractFileName(tfn)+"\"", LL_DEBUG);
				std::string h;
				if(!diff_file)
				{
					h=hash(tf);
				}
				else
				{
					h=hash_with_patch(old_file, tf);
				}

				Server->destroy(tf);
				if(old_file!=NULL)
				{
					Server->destroy(old_file);
				}
				
				CWData data;
				data.addString(temp_fn);
				data.addInt(backupid);
				data.addChar(incremental);
				data.addString(tfn);
				data.addString(hashpath);
				data.addString(h);
				data.addString(hashoutput_fn);
				data.addString(old_file_fn);

				output->Write(data.getDataPtr(), data.getDataSize() );
			}
		}
	}
}