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 }
void ls_switch_file( ChannelLog *cl ) { static char tmbuf[MAXPATH]; static char newfname[MAXPATH]; static char oldfname[MAXPATH]; int res; /* no need to switch, its not opened */ if( cl->logfile == NULL ) return; ls_close_log( cl ); /* check if the target directory exists */ if( os_create_dir( LogServ.savedir ) != NS_SUCCESS ) { return; } os_strftime( tmbuf, MAXPATH, "%d%m%Y%H%M%S", os_localtime( &me.now ) ); ircsnprintf( newfname, MAXPATH, "%s/%s-%s.log", LogServ.savedir, cl->filename, tmbuf ); ircsnprintf( oldfname, MAXPATH, "%s/%s.log", LogServ.logdir, cl->filename ); res = os_rename( oldfname, newfname ); if( res != 0 ) { nlog( LOG_CRITICAL, "Couldn't rename file %s: %s", oldfname, os_strerror() ); return; } nlog( LOG_NORMAL, "Switched Logfile for %s from %s to %s", cl->channame, oldfname, newfname ); }
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; }
bool create_subvolume(std::string subvolume_folder) { #ifdef _WIN32 return os_create_dir(subvolume_folder); #else int rc=system((btrfs_cmd+" subvolume create \""+subvolume_folder+"\"").c_str()); system(("chown urbackup:urbackup \""+subvolume_folder+"\"").c_str()); return rc==0; #endif }
bool os_create_dir_recursive(std::string fn) { if(fn.empty()) return false; bool b=os_create_dir(fn); if(!b) { b=os_create_dir_recursive(ExtractFilePath(fn)); if(!b) return false; return os_create_dir(fn); } else { return true; } }
bool create_subvolume(int mode, std::string subvolume_folder) { #ifdef _WIN32 return os_create_dir(subvolume_folder); #else if(mode==mode_btrfs) { int rc=exec_wait(find_btrfs_cmd(), true, "subvolume", "create", subvolume_folder.c_str(), NULL); chown_dir(subvolume_folder); return rc==0; } else if(mode==mode_zfs) { zfs_elevate(); int rc=exec_wait(find_zfs_cmd(), true, "create", "-p", subvolume_folder.c_str(), NULL); chown_dir(subvolume_folder); return rc==0; } return false; #endif }
static int ls_open_log( ChannelLog *cl ) { static char fname[MAXPATH]; /* first, make sure the logdir dir exists */ if( os_create_dir( LogServ.logdir ) != NS_SUCCESS ) { return NS_FAILURE; } /* copy name to the filename holder( in case of invalid paths ) */ strlcpy( cl->filename, cl->channame, MAXPATH ); ircsnprintf( fname, MAXPATH, "%s/%s.log", LogServ.logdir, make_safe_filename( cl->filename ) ); /* open the file */ cl->logfile = os_fopen( fname, "a" ); if( cl->logfile == NULL ) { nlog( LOG_CRITICAL, "Could not open %s for appending: %s", cl->filename, os_strerror() ); return NS_FAILURE; } dlog( DEBUG1, "Opened %s for appending", cl->filename ); cl->ts_open = me.now; logging_funcs[LogServ.logtype][LGSMSG_START]( cl, NULL ); return NS_SUCCESS; }
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; } } }
int main(int argc, char *argv[]) { if(argc<2) { std::cout << "Not enough parameters" << std::endl; return 1; } std::string cmd=argv[1]; std::string backupfolder=getBackupfolderPath(); if(backupfolder.empty()) { std::cout << "Backupfolder not set" << std::endl; return 1; } #ifndef _WIN32 if(seteuid(0)!=0) { std::cout << "Cannot become root user" << std::endl; return 1; } #endif if(cmd=="create") { if(argc<4) { std::cout << "Not enough parameters for create" << std::endl; return 1; } std::string clientname=handleFilename(argv[2]); std::string name=handleFilename(argv[3]); std::string subvolume_folder=backupfolder+os_file_sepn()+clientname+os_file_sepn()+name; return create_subvolume(subvolume_folder)?0:1; } else if(cmd=="snapshot") { if(argc<5) { std::cout << "Not enough parameters for snapshot" << std::endl; return 1; } std::string clientname=handleFilename(argv[2]); std::string src_name=handleFilename(argv[3]); std::string dst_name=handleFilename(argv[4]); std::string subvolume_src_folder=backupfolder+os_file_sepn()+clientname+os_file_sepn()+src_name; std::string subvolume_dst_folder=backupfolder+os_file_sepn()+clientname+os_file_sepn()+dst_name; return create_snapshot(subvolume_src_folder, subvolume_dst_folder)?0:1; } else if(cmd=="remove") { if(argc<4) { std::cout << "Not enough parameters for remove" << std::endl; return 1; } std::string clientname=handleFilename(argv[2]); std::string name=handleFilename(argv[3]); std::string subvolume_folder=backupfolder+os_file_sepn()+clientname+os_file_sepn()+name; return remove_subvolume(subvolume_folder)?0:1; } else if(cmd=="test") { std::string clientdir=backupfolder+os_file_sepn()+"testA54hj5luZtlorr494"; if(os_create_dir(clientdir)) { if(!create_subvolume(clientdir+os_file_sepn()+"A") ) { std::cout << "Creating test subvolume failed" << std::endl; os_remove_dir(clientdir); return 1; } bool suc=true; if(!create_snapshot(clientdir+os_file_sepn()+"A", clientdir+os_file_sepn()+"B") ) { std::cout << "Creating test snapshot failed" << std::endl; suc=false; } if(suc) { writestring("test", clientdir+os_file_sepn()+"A"+os_file_sepn()+"test"); if(!os_create_hardlink(clientdir+os_file_sepn()+"B"+os_file_sepn()+"test", clientdir+os_file_sepn()+"A"+os_file_sepn()+"test", true, NULL)) { std::cout << "Cross subvolume reflink failed" << std::endl; suc=false; } if(getFile(clientdir+os_file_sepn()+"B"+os_file_sepn()+"test")!="test") { std::cout << "Cannot read reflinked file" << std::endl; suc=false; } } if(!remove_subvolume(clientdir+os_file_sepn()+"A") ) { std::cout << "Removing subvolume A failed" << std::endl; suc=false; } if(!remove_subvolume(clientdir+os_file_sepn()+"B") ) { std::cout << "Removing subvolume B failed" << std::endl; suc=false; } if(!os_remove_dir(clientdir)) { std::cout << "Removing test clientdir failed" << std::endl; return 1; } if(!suc) { return 1; } } else { std::cout << "Creating test clientdir \"" << clientdir << "\" failed" << std::endl; return 1; } return 0; } else if(cmd=="issubvolume") { if(argc<4) { std::cout << "Not enough parameters for issubvolume" << std::endl; return 1; } std::string clientname=handleFilename(argv[2]); std::string name=handleFilename(argv[3]); std::string subvolume_folder=backupfolder+os_file_sepn()+clientname+os_file_sepn()+name; return is_subvolume(subvolume_folder)?0:1; } else { std::cout << "Command not found" << std::endl; return 1; }
bool LMDBFileIndex::create_env() { int rc; if(env==NULL) { rc = mdb_env_create(&env); if(rc) { Server->Log("LMDB: Failed to create LMDB env ("+(std::string)mdb_strerror(rc)+")", LL_ERROR); return false; } { std::auto_ptr<IFile> lmdb_f(Server->openFile("urbackup/fileindex/backup_server_files_index.lmdb", MODE_READ)); if(lmdb_f.get()!=NULL) { while(lmdb_f->Size()>static_cast<_i64>(map_size)) { map_size*=2; } } } rc = mdb_env_set_maxreaders(env, 4094); if (rc) { Server->Log("LMDB: Failed to set max readers (" + (std::string)mdb_strerror(rc) + ")", LL_ERROR); return false; } rc = mdb_env_set_mapsize(env, map_size); if(rc) { Server->Log("LMDB: Failed to set map size ("+(std::string)mdb_strerror(rc)+")", LL_ERROR); return false; } os_create_dir("urbackup/fileindex"); unsigned int flags = MDB_NOSUBDIR|MDB_NOMETASYNC; if(no_sync) { flags|=MDB_NOSYNC; } rc = mdb_env_open(env, "urbackup/fileindex/backup_server_files_index.lmdb", flags, 0664); if(rc) { Server->Log("LMDB: Failed to open LMDB database file ("+(std::string)mdb_strerror(rc)+")", LL_ERROR); return false; } MDB_txn* l_txn; rc = mdb_txn_begin(env, NULL, flags, &l_txn); if (rc) { Server->Log("LMDB: Failed to open transaction handle for dbi open (" + (std::string)mdb_strerror(rc) + ")", LL_ERROR); return false; } rc = mdb_dbi_open(l_txn, NULL, 0, &dbi); if (rc) { Server->Log("LMDB: Failed to open database (" + (std::string)mdb_strerror(rc) + ")", LL_ERROR); return false; } rc = mdb_txn_commit(l_txn); if (rc) { Server->Log("LMDB: Failed to commit txn for dbi handle (" + (std::string)mdb_strerror(rc) + ")", LL_ERROR); return false; } return true; } else { return true; } }
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; } }