std::vector<SShadowCopy> ClientDAO::getShadowcopies(void) { db_results res=q_get_shadowcopies->Read(); q_get_shadowcopies->Reset(); std::vector<SShadowCopy> ret; for(size_t i=0;i<res.size();++i) { db_single_result &r=res[i]; SShadowCopy sc; sc.id=watoi(r[L"id"]); memcpy(&sc.vssid, r[L"vssid"].c_str(), sizeof(GUID) ); memcpy(&sc.ssetid, r[L"ssetid"].c_str(), sizeof(GUID) ); sc.target=r[L"target"]; sc.path=r[L"path"]; sc.tname=r[L"tname"]; sc.orig_target=r[L"orig_target"]; sc.filesrv=r[L"filesrv"]==L"0"?false:true; sc.vol=r[L"vol"]; sc.passedtime=watoi(r[L"passedtime"]); sc.refs=watoi(r[L"refs"]); sc.starttoken=r[L"starttoken"]; ret.push_back(sc); } return ret; }
void updateArchiveSettings(int clientid, str_map &GET, IDatabase *db) { int i=0; IQuery *q=db->Prepare("DELETE FROM settings_db.automatic_archival WHERE clientid=?"); q->Bind(clientid); q->Write(); q=db->Prepare("INSERT INTO settings_db.automatic_archival (next_archival, interval, interval_unit, length, length_unit, backup_types, clientid, archive_window) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); while(GET.find(L"archive_every_"+convert(i))!=GET.end()) { _i64 archive_next=watoi64(GET[L"archive_next_"+convert(i)]); int archive_every=watoi(GET[L"archive_every_"+convert(i)]); int archive_for=watoi(GET[L"archive_for_"+convert(i)]); std::wstring backup_type_str=GET[L"archive_backup_type_"+convert(i)]; int backup_types=ServerAutomaticArchive::getBackupTypes(backup_type_str); if(archive_next<0) { if(clientid==0) { q->Bind(0); } else { q->Bind(Server->getTimeSeconds()); } } else { q->Bind(archive_next); } q->Bind(archive_every); q->Bind(GET[L"archive_every_unit_"+convert(i)]); q->Bind(archive_for); q->Bind(GET[L"archive_for_unit_"+convert(i)]); q->Bind(backup_types); q->Bind(clientid); q->Bind(GET[L"archive_window_"+convert(i)]); q->Write(); q->Reset(); ++i; } IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid="+nconvert(clientid)+" AND key=?"); if(clientid!=0) { IQuery *q_update=db->Prepare("UPDATE settings_db.settings SET value=? WHERE key=? AND clientid="+nconvert(clientid)); IQuery *q_insert=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES (?,?,"+nconvert(clientid)+")"); updateSetting(L"overwrite_archive_settings", L"true", q_get, q_update, q_insert); } else { db->Write("DELETE FROM settings_db.settings WHERE key='archive_settings_copied'"); } }
void getArchiveSettings(JSON::Object &obj, IDatabase *db, int clientid) { IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid="+nconvert(clientid)+" AND key=?"); q_get->Bind("overwrite"); db_results res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") clientid=0; q_get->Bind("overwrite_archive_settings"); res=q_get->Read(); if(res.empty() || res[0][L"value"]!=L"true") clientid=0; IQuery *q=db->Prepare("SELECT next_archival, interval, interval_unit, length, length_unit, backup_types FROM settings_db.automatic_archival WHERE clientid=?"); q->Bind(clientid); res=q->Read(); JSON::Array arr; for(size_t i=0;i<res.size();++i) { _i64 archive_next=watoi64(res[i][L"next_archival"]); JSON::Object ca; ca.set("next_archival", res[i][L"next_archival"]); ca.set("archive_every", watoi(res[i][L"interval"])); ca.set("archive_every_unit", res[i][L"interval_unit"]); ca.set("archive_for", watoi(res[i][L"length"])); ca.set("archive_for_unit", res[i][L"length_unit"]); ca.set("archive_backup_type", ServerAutomaticArchive::getBackupType(watoi(res[i][L"backup_types"]))); ca.set("archive_window", res[i][L"archive_window"]); if(archive_next>0 && clientid!=0) { _i64 tl=archive_next-(_i64)Server->getTimeSeconds(); ca.set("archive_timeleft", tl); } else { ca.set("archive_timeleft", "-"); } arr.add(ca); } obj.set("archive_settings", arr); }
SDeviceInfo ChangeJournalWatcher::getDeviceInfo(const std::wstring &name) { q_get_dev_id->Bind(name); db_results res=q_get_dev_id->Read(); q_get_dev_id->Reset(); SDeviceInfo r; r.has_info=false; if(!res.empty()) { r.has_info=true; r.journal_id=os_atoi64(wnarrow(res[0][L"journal_id"])); r.last_record=os_atoi64(wnarrow(res[0][L"last_record"])); r.index_done=watoi(res[0][L"index_done"])>0; } return r; }
int ClientDAO::modShadowcopyRefCount(int id, int m) { q_get_shadowcopy_refcount->Bind(id); db_results res=q_get_shadowcopy_refcount->Read(); q_get_shadowcopy_refcount->Reset(); if(!res.empty()) { int refs=watoi(res[0][L"refs"]); refs+=m; q_set_shadowcopy_refcount->Bind(refs); q_set_shadowcopy_refcount->Bind(id); q_set_shadowcopy_refcount->Write(); q_set_shadowcopy_refcount->Reset(); return refs; } return -1; }
std::vector<SBackupDir> ClientDAO::getBackupDirs(void) { db_results res=q_get_dirs->Read(); q_get_dirs->Reset(); std::vector<SBackupDir> ret; for(size_t i=0;i<res.size();++i) { SBackupDir dir; dir.id=watoi(res[i][L"id"]); dir.tname=res[i][L"name"]; dir.path=res[i][L"path"]; if(dir.tname!=L"*") ret.push_back(dir); } return ret; }
int ServerAutomaticArchive::getNonArchivedFileBackup(int backup_types, int clientid) { std::string incremental; if(backup_types & backup_type_full_file && backup_types & backup_type_incr_file) incremental=""; else if( backup_types & backup_type_full_file ) incremental=" AND incremental<>0"; else if( backup_types & backup_type_incr_file) incremental=" AND incremental=0"; IQuery *q_get_backups=db->Prepare("SELECT id FROM backups WHERE complete=1 AND archived=0 AND clientid=?"+incremental+" ORDER BY backuptime DESC LIMIT 1"); q_get_backups->Bind(clientid); db_results res=q_get_backups->Read(); if(!res.empty()) return watoi(res[0][L"id"]); else return 0; }
SStatus Connector::getStatus(void) { std::string d=getResponse("STATUS",""); std::vector<std::string> toks; Tokenize(d, toks, "#"); SStatus ret; ret.pause=false; ret.capa=0; if(toks.size()>0) ret.lastbackupdate=wxString::FromUTF8(toks[0].c_str() ); if(toks.size()>1) ret.status=wxString::FromUTF8(toks[1].c_str() ); if(toks.size()>2) ret.pcdone=wxString::FromUTF8(toks[2].c_str() ); if(toks.size()>3) { if(toks[3]=="P") ret.pause=true; else if(toks[3]=="NP") ret.pause=false; } if(toks.size()>4) { std::map<std::wstring,std::wstring> params; ParseParamStr(toks[4], ¶ms); std::map<std::wstring,std::wstring>::iterator it_capa=params.find(L"capa"); if(it_capa!=params.end()) { ret.capa=watoi(it_capa->second); } std::map<std::wstring,std::wstring>::iterator it_new_server=params.find(L"new_ident"); if(it_new_server!=params.end()) { ret.new_server=wnarrow(it_new_server->second); } } return ret; }
bool ClientDAO::getFiles(std::wstring path, std::vector<SFile> &data) { q_get_files->Bind(path); db_results res=q_get_files->Read(); q_get_files->Reset(); if(res.size()==0) return false; std::wstring &qdata=res[0][L"data"]; if(qdata.empty()) return true; int num=watoi(res[0][L"num"]); char *ptr=(char*)&qdata[0]; while(ptr-(char*)&qdata[0]<num) { SFile f; unsigned short ss; memcpy(&ss, ptr, sizeof(unsigned short)); ptr+=sizeof(unsigned short); std::string tmp; tmp.resize(ss); memcpy(&tmp[0], ptr, ss); f.name=Server->ConvertToUnicode(tmp); ptr+=ss; memcpy(&f.size, ptr, sizeof(int64)); ptr+=sizeof(int64); memcpy(&f.last_modified, ptr, sizeof(int64)); ptr+=sizeof(int64); char isdir=*ptr; ++ptr; if(isdir==0) f.isdir=false; else f.isdir=true; data.push_back(f); } return true; }
DLLEXPORT void LoadActions(IServer* pServer) { Server=pServer; std::string compress_file = Server->getServerParameter("compress"); if(!compress_file.empty()) { IFile* in = Server->openFile(compress_file, MODE_READ_SEQUENTIAL); if(in==NULL) { Server->Log("Cannot open file \""+compress_file+"\" to compress", LL_ERROR); exit(1); } { Server->deleteFile(compress_file+".urz"); CompressedFile compFile(compress_file+".urz", MODE_RW_CREATE); if(compFile.hasError()) { Server->Log("Error opening compressed file", LL_ERROR); exit(3); } char buffer[32768]; _u32 read; do { read = in->Read(buffer, 32768); if(read>0) { if(compFile.Write(buffer, read)!=read) { Server->Log("Error writing to compressed file", LL_ERROR); exit(2); } } } while (read>0); compFile.finish(); delete in; } exit(0); } std::string decompress = Server->getServerParameter("decompress"); if(!decompress.empty()) { bool selected_via_gui=false; #ifdef _WIN32 if(decompress=="SelectViaGUI") { std::string filter; filter += "Compressed image files (*.vhdz)"; filter += '\0'; filter += "*.vhdz"; filter += '\0'; filter += '\0'; std::vector<std::string> res = file_via_dialog("Please select compressed image file to decompress", filter, false, true, ""); if(!res.empty()) { decompress = res[0]; } else { decompress.clear(); } if(decompress.empty()) { exit(1); } else { selected_via_gui=true; } } #endif std::string targetName = decompress; if(findextension(decompress)!="vhdz" && findextension(decompress)!="urz") { Server->Log("Unknown file extension: "+findextension(decompress), LL_ERROR); exit(1); } if(!Server->getServerParameter("output_fn").empty() && !selected_via_gui) { targetName = Server->getServerParameter("output_fn"); } bool b = decompress_vhd(decompress, targetName); exit(b?0:3); } std::string assemble = Server->getServerParameter("assemble"); if(!assemble.empty()) { bool selected_via_gui=false; std::vector<std::string> input_files; std::string output_file; #ifdef _WIN32 if(assemble=="SelectViaGUI") { std::string filter; filter += "Image files (*.vhdz;*.vhd)"; filter += '\0'; filter += "*.vhdz;*.vhd"; filter += '\0'; /*filter += L"Image files (*.vhd)"; filter += '\0'; filter += L"*.vhd"; filter += '\0';*/ filter += '\0'; std::vector<std::string> new_input_files; do { new_input_files = file_via_dialog("Please select all the images to assemble into one image. Cancel once finished.", filter, true, true, ""); input_files.insert(input_files.end(), new_input_files.begin(), new_input_files.end()); } while (!new_input_files.empty()); filter.clear(); filter += "Image file (*.vhd)"; filter += '\0'; filter += "*.vhd"; filter += '\0'; filter += '\0'; std::vector<std::string> output_files = file_via_dialog("Please select where to save the output image", filter, false, false, "vhd"); if(!output_files.empty()) { output_file = output_files[0]; } selected_via_gui=true; } #endif if(!selected_via_gui) { Tokenize(assemble, input_files, ";"); output_file = Server->getServerParameter("output_file"); } if(input_files.empty()) { Server->Log("No input files selected", LL_ERROR); exit(1); } if(output_file.empty()) { Server->Log("No output file selected", LL_ERROR); exit(1); } bool b = assemble_vhd(input_files, output_file); exit(b?0:3); } std::string devinfo=Server->getServerParameter("devinfo"); if(!devinfo.empty()) { FSNTFS ntfs("\\\\.\\"+devinfo+":", IFSImageFactory::EReadaheadMode_None, false, NULL); if(!ntfs.hasError()) { Server->Log("Used Space: "+convert(ntfs.calculateUsedSpace())+" of "+convert(ntfs.getSize())); Server->Log(convert(((float)ntfs.calculateUsedSpace()/(float)ntfs.getSize())*100.0f)+" %"); } } std::string vhdcopy_in=Server->getServerParameter("vhdcopy_in"); if(!vhdcopy_in.empty()) { Server->Log("VHDCopy."); VHDFile in(vhdcopy_in, true,0); if(in.isOpen()==false) { Server->Log("Error opening VHD-File \""+vhdcopy_in+"\"", LL_ERROR); exit(4); } uint64 vhdsize=in.getSize(); float vhdsize_gb=(vhdsize/1024)/1024.f/1024.f; uint64 vhdsize_mb=vhdsize/1024/1024; Server->Log("VHD Info: Size: "+convert(vhdsize_gb)+" GB "+convert(vhdsize_mb)+" MB",LL_INFO); unsigned int vhd_blocksize=in.getBlocksize(); std::string vhdcopy_out=Server->getServerParameter("vhdcopy_out"); if(vhdcopy_out.empty()) { Server->Log("'vhdcopy_out' not specified. Not copying.", LL_ERROR); exit(5); } else { IFile *out=Server->openFile(vhdcopy_out, MODE_RW); if(out==NULL) { Server->Log("Couldn't open output file", LL_ERROR); exit(6); } else { std::string skip_s=Server->getServerParameter("skip"); int skip=1024*512; if(!skip_s.empty()) { skip=atoi(skip_s.c_str()); } else if (is_disk_mbr(vhdcopy_in + ".mbr")) { skip = 0; } Server->Log("Skipping "+convert(skip)+" bytes...", LL_INFO); in.Seek(skip); char buffer[4096]; size_t read; int last_pc=0; int p_skip=0; uint64 currpos=skip; bool is_ok=true; out->Seek(0); while(currpos%vhd_blocksize!=0) { is_ok=in.Read(buffer, 512, read); if(read>0) { _u32 rc=out->Write(buffer, (_u32)read); if(rc!=read) { Server->Log("Writing to output file failed", LL_ERROR); exit(7); } } currpos+=read; } if(currpos!=skip) { Server->Log("First VHD sector at "+convert(currpos), LL_INFO); } do { if(in.has_sector()) { is_ok=in.Read(buffer, 4096, read); if(read>0) { _u32 rc=out->Write(buffer, (_u32)read); if(rc!=read) { Server->Log("Writing to output file failed", LL_ERROR); exit(7); } } currpos+=read; } else { read=4096; currpos+=read; in.Seek(currpos); out->Seek(currpos-skip); } ++p_skip; if(p_skip>100) { p_skip=0; int pc=(int)(((float)currpos/(float)vhdsize)*100.f+0.5f); if(pc!=last_pc) { Server->Log(convert(pc)+"%", LL_INFO); last_pc=pc; } } } while( read==4096 && is_ok ); Server->destroy(out); Server->Log("Copy process finished successfully.", LL_INFO); exit(0); } } } std::string hashfilecomp_1=Server->getServerParameter("hashfilecomp_1"); if(!hashfilecomp_1.empty()) { IFile *hf1=Server->openFile(hashfilecomp_1, MODE_READ); IFile *hf2=Server->openFile(Server->getServerParameter("hashfilecomp_2"), MODE_READ); if(hf1==NULL || hf2==NULL ) { Server->Log("Error opening hashfile", LL_ERROR); } else { size_t h_equal=0; size_t h_diff=0; _i64 fsize=hf1->Size(); for(_i64 p=0;p<fsize;p+=32) { char buf1[32]; hf1->Read(buf1, 32); char buf2[32]; hf2->Read(buf2, 32); if( memcmp(buf1, buf2, 32)==0) { ++h_equal; } else { ++h_diff; } } std::cout << "Hashfile analysis: " << h_equal << " equal hashes; " << h_diff << " differences " << std::endl; } exit(5); } std::string vhdinfo=Server->getServerParameter("vhdinfo"); if(!vhdinfo.empty()) { std::cout << "--VHDINFO--" << std::endl; VHDFile in(vhdinfo, true,0); if(in.isOpen()==false) { Server->Log("Error opening VHD-File \""+vhdinfo+"\"", LL_ERROR); exit(4); } uint64 vhdsize=in.getSize(); float vhdsize_gb=(vhdsize/1024)/1024.f/1024.f; uint64 vhdsize_mb=vhdsize/1024/1024; std::cout << ("VHD Info: Size: "+convert(vhdsize_gb)+" GB "+convert(vhdsize_mb)+" MB") << std::endl; std::cout << "Blocksize: " << in.getBlocksize() << " Bytes" << std::endl; uint64 new_blocks=0; uint64 total_blocks=0; unsigned int bs=in.getBlocksize(); for(uint64 pos=0;pos<vhdsize;pos+=bs) { in.Seek(pos); if(in.this_has_sector()) { ++new_blocks; } ++total_blocks; } std::cout << "Blocks: " << new_blocks << "/" << total_blocks << std::endl; exit(3); } std::string image_verify=Server->getServerParameter("image_verify"); if(!image_verify.empty()) { std::auto_ptr<IVHDFile> in(open_device_file(image_verify)); if(in.get()==NULL || in->isOpen()==false) { Server->Log("Error opening Image-File \""+image_verify+"\"", LL_ERROR); exit(4); } std::string s_hashfile=Server->getServerParameter("hashfile"); bool has_hashfile=true; if(s_hashfile.empty()) { has_hashfile=false; s_hashfile=image_verify+".hash"; } IFile *hashfile=Server->openFile(s_hashfile, MODE_READ); if(hashfile==NULL) { Server->Log("Error opening hashfile"); exit(5); } bool verify_all = Server->getServerParameter("verify_all")=="true"; if(verify_all) { Server->Log("Verifying empty blocks"); } const int64 vhd_blocksize=(1024*1024)/2; int skip=1024*512; std::string s_verify_skip = Server->getServerParameter("verify_skip"); if (!s_verify_skip.empty()) { skip = watoi(s_verify_skip); } in->Seek(skip); uint64 currpos=skip; uint64 size=in->getSize(); sha256_ctx ctx; sha256_init(&ctx); char buf[512]; int diff=0; int diff_w=0; size_t ok_blocks=0; int last_pc=0; unsigned char dig_z[32]; bool has_dig_z=false; for(;currpos<size;currpos+=vhd_blocksize) { in->Seek(currpos); bool has_sector=verify_all || in->this_has_sector(vhd_blocksize); if(!has_sector && !has_dig_z) { for(unsigned int i=0;i<vhd_blocksize;i+=512) { size_t read; in->Read(buf, 512, read); sha256_update(&ctx, (unsigned char*)buf, 512); } sha256_final(&ctx, dig_z); sha256_init(&ctx); has_dig_z=true; } unsigned char dig_r[32]; unsigned char dig_f[32]; if(has_sector) { for(unsigned int i=0;i<vhd_blocksize && currpos+i<size;i+=512) { size_t read; in->Read(buf, 512, read); sha256_update(&ctx, (unsigned char*)buf, 512); } _u32 dr=hashfile->Read((char*)dig_f, 32); if( dr!=32 ) { Server->Log("Could not read hash from file", LL_ERROR); } sha256_final(&ctx, dig_r); sha256_init(&ctx); } else { hashfile->Read((char*)dig_f, 32); memcpy(dig_r, dig_z, 32); } if(memcmp(dig_r, dig_f, 32)!=0) { ++diff; Server->Log("Different blocks: "+convert(diff)+" at pos "+convert(currpos)+" has_sector="+convert(has_sector)); } else if(has_sector && has_hashfile) { ++diff_w; Server->Log("Wrong difference: "+convert(diff_w)+" at pos "+convert(currpos)); } else { ++ok_blocks; } int pc=(int)((float)((float)currpos/(float)size)*100.f+0.5f); if(pc!=last_pc) { last_pc=pc; Server->Log("Checking hashfile: "+convert(pc)+"%"); } } if(diff==0) { Server->Log("Hashfile does match"); } Server->Log("Blocks with correct hash: "+convert(ok_blocks)); Server->Log("Different blocks: "+convert(diff)); Server->Log("Wrong differences: "+convert(diff_w)); exit(diff==0?0:7); } std::string device_verify=Server->getServerParameter("device_verify"); if(!device_verify.empty()) { std::auto_ptr<IVHDFile> in(open_device_file(device_verify)); if(in.get()==NULL || in->isOpen()==false) { Server->Log("Error opening Image-File \""+device_verify+"\"", LL_ERROR); exit(4); } int skip=1024*512; FileWrapper wrapper(in.get(), skip); FSNTFS fs(&wrapper, IFSImageFactory::EReadaheadMode_None, false, NULL); if(fs.hasError()) { Server->Log("Error opening device file", LL_ERROR); exit(3); } PrintInfo(&fs); std::string s_hashfile=Server->getServerParameter("hash_file"); if(s_hashfile.empty()) { s_hashfile = device_verify+".hash"; } IFile *hashfile=Server->openFile(s_hashfile, MODE_READ); if(hashfile==NULL) { Server->Log("Error opening hashfile "+s_hashfile); exit(7); } unsigned int ntfs_blocksize=(unsigned int)fs.getBlocksize(); unsigned int vhd_sectorsize=(1024*1024)/2; uint64 currpos=0; uint64 size=fs.getSize(); sha256_ctx ctx; sha256_init(&ctx); int diff=0; int last_pc=0; int mixed=0; std::vector<char> zerobuf; zerobuf.resize(ntfs_blocksize); memset(&zerobuf[0], 0, ntfs_blocksize); for(;currpos<size;currpos+=ntfs_blocksize) { bool has_block=fs.hasBlock(currpos/ntfs_blocksize); if(has_block) { fs_buffer buf(&fs, fs.readBlock(currpos/ntfs_blocksize)); if(buf.get()==NULL) { Server->Log("Could not read block "+convert(currpos/ntfs_blocksize), LL_ERROR); } else { sha256_update(&ctx, (unsigned char*)buf.get(), ntfs_blocksize); } mixed = mixed | 1; } else { sha256_update(&ctx, (unsigned char*)&zerobuf[0], ntfs_blocksize); mixed = mixed | 2; } if( (currpos+ntfs_blocksize)%vhd_sectorsize==0 ) { unsigned char dig_r[32]; unsigned char dig_f[32]; _u32 dr=hashfile->Read((char*)dig_f, 32); if( dr!=32 ) { Server->Log("Could not read hash from file", LL_ERROR); } sha256_final(&ctx, dig_r); sha256_init(&ctx); if(memcmp(dig_r, dig_f, 32)!=0 && mixed!=2) { ++diff; Server->Log("Different blocks: "+convert(diff)+" at pos "+convert(currpos)+" mixed = "+ (mixed==3? "true":"false")+" ("+convert(mixed)+")" ); } mixed=0; } int pc=(int)((float)((float)currpos/(float)size)*100.f+0.5f); if(pc!=last_pc) { last_pc=pc; Server->Log("Checking device hashsums: "+convert(pc)+"%"); } } if(diff>0) { Server->Log("Device does not match hash file"); } Server->Log("Different blocks: "+convert(diff)); exit(7); } std::string vhd_cmp=Server->getServerParameter("vhd_cmp"); if(!vhd_cmp.empty()) { VHDFile in(vhd_cmp, true,0); if(in.isOpen()==false) { Server->Log("Error opening VHD-File \""+vhd_cmp+"\"", LL_ERROR); exit(4); } std::string other=Server->getServerParameter("other"); VHDFile other_in(other, true,0); if(other_in.isOpen()==false) { Server->Log("Error opening VHD-File \""+other+"\"", LL_ERROR); exit(4); } unsigned int blocksize=in.getBlocksize(); int skip=1024*512; in.Seek(skip); other_in.Seek(skip); uint64 currpos=skip; uint64 size=(std::min)(in.getSize(), other_in.getSize()); char buf1[512]; char buf2[512]; int diff=0; int last_pc=0; for(;currpos<size;currpos+=blocksize) { in.Seek(currpos); other_in.Seek(currpos); bool has_sector=in.this_has_sector() || other_in.this_has_sector(); if(in.this_has_sector() && !other_in.this_has_sector()) { Server->Log("Sector only in file 1 at pos "+convert(currpos)); } if(!in.this_has_sector() && other_in.this_has_sector()) { Server->Log("Sector only in file 2 at pos "+convert(currpos)); } if(has_sector) { bool hdiff=false; for(unsigned int i=0;i<blocksize;i+=512) { size_t read; in.Read(buf1, 512, read); other_in.Read(buf2, 512, read); int mr=memcmp(buf1, buf2, 512); if(mr!=0) { int n=0; for(size_t i=0;i<512;++i) { if(buf1[i]!=buf2[i]) { ++n; } } if(n==2) { NTFSFileRecord *fr=(NTFSFileRecord*)buf1; if(fr->magic[0]=='F' && fr->magic[1]=='I' && fr->magic[2]=='L' && fr->magic[3]=='E' ) { MFTAttribute attr; attr.length=fr->attribute_offset; int pos=0; do { pos+=attr.length; memcpy((char*)&attr, buf1+pos, sizeof(MFTAttribute) ); if(attr.type==0x30 && attr.nonresident==0) //FILENAME { MFTAttributeFilename fn; memcpy((char*)&fn, buf1+pos+attr.attribute_offset, sizeof(MFTAttributeFilename) ); std::string fn_uc; fn_uc.resize(fn.filename_length*2); memcpy(&fn_uc[0], buf1+pos+attr.attribute_offset+sizeof(MFTAttributeFilename), fn.filename_length*2); Server->Log("Filename="+Server->ConvertFromUTF16(fn_uc) , LL_DEBUG); } Server->Log("Attribute Type: "+convert(attr.type)+" nonresident="+convert(attr.nonresident)+" length="+convert(attr.length), LL_DEBUG); }while( attr.type!=0xFFFFFFFF && attr.type!=0x80); } for(size_t i=0;i<512;++i) { if(buf1[i]!=buf2[i]) { Server->Log("Position "+convert(i)+": "+convert((int)buf1[i])+"<->"+convert((int)buf2[i])); } } } hdiff=true; break; } } if(hdiff) { ++diff; Server->Log("Different blocks: "+convert(diff)+" at pos "+convert(currpos)); } } int pc=(int)((float)((float)currpos/(float)size)*100.f+0.5f); if(pc!=last_pc) { last_pc=pc; Server->Log("Checking hashfile: "+convert(pc)+"%"); } } Server->Log("Different blocks: "+convert(diff)); exit(7); } std::string vhd_fixmftmirr=Server->getServerParameter("vhd_checkmftmirr"); if(!vhd_fixmftmirr.empty()) { VHDFile vhd(vhd_fixmftmirr, false, 0); vhd.addVolumeOffset(1024*512); if(vhd.isOpen()==false) { Server->Log("Could not open VHD file", LL_ERROR); exit(7); } if(Server->getServerParameter("fix")!="true") { FSNTFS fs(&vhd, IFSImageFactory::EReadaheadMode_None, false, NULL); if(fs.hasError()) { Server->Log("NTFS filesystem has errors", LL_ERROR); } exit(7); } else { FSNTFS fs(&vhd, IFSImageFactory::EReadaheadMode_None, false, NULL); if(fs.hasError()) { Server->Log("NTFS filesystem has errors", LL_ERROR); } exit(7); } exit(0); } #ifdef _DEBUG std::string fibmap_test_fn = Server->getServerParameter("fibmap_test"); if (!fibmap_test_fn.empty()) { #ifdef __linux__ fibmap_test(fibmap_test_fn, Server->getServerParameter("bitmap_source")); #endif exit(0); } #endif imagepluginmgr=new CImagePluginMgr; Server->RegisterPluginThreadsafeModel( imagepluginmgr, "fsimageplugin"); #ifndef STATIC_PLUGIN Server->Log("Loaded -fsimageplugin- plugin", LL_INFO); #endif }
void LMDBFileIndex::create(get_data_callback_t get_data_callback, void *userdata) { begin_txn(0); IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES_NEW); ServerFilesDao filesdao(db); size_t n_done=0; size_t n_rows=0; SIndexKey last; int64 last_prev_entry; int64 last_id; db_results res; do { res=get_data_callback(n_done, n_rows, userdata); ++n_rows; for(size_t i=0;i<res.size();++i) { const std::string& shahash=res[i]["shahash"]; int64 id = watoi64(res[i]["id"]); SIndexKey key(reinterpret_cast<const char*>(shahash.c_str()), watoi64(res[i]["filesize"]), watoi(res[i]["clientid"])); int64 next_entry = watoi64(res[i]["next_entry"]); int64 prev_entry = watoi64(res[i]["prev_entry"]); int pointed_to = watoi(res[i]["pointed_to"]); assert(memcmp(&last, &key, sizeof(SIndexKey))!=1); if(key==last) { if(last_prev_entry==0) { filesdao.setPrevEntry(id, last_id); } if(next_entry==0 && (last_prev_entry==0 || last_prev_entry==id) ) { filesdao.setNextEntry(last_id, id); } if(pointed_to) { filesdao.setPointedTo(0, id); } last=key; last_id=id; last_prev_entry=prev_entry; continue; } else { if(!pointed_to) { filesdao.setPointedTo(1, id); } } put(key, id, MDB_APPEND); if(_has_error) { Server->Log("LMDB error after putting element. Error state interrupting..", LL_ERROR); return; } if(n_done % 1000 == 0 && n_done>0) { if ((Server->getFailBits() & IServer::FAIL_DATABASE_CORRUPTED) || (Server->getFailBits() & IServer::FAIL_DATABASE_IOERR) || (Server->getFailBits() & IServer::FAIL_DATABASE_FULL)) { Server->Log("Database error. Stopping.", LL_ERROR); return; } Server->Log("File entry index contains "+convert(n_done)+" entries now.", LL_INFO); } if(n_done % c_create_commit_n == 0 && n_done>0) { commit_transaction(); begin_txn(0); } ++n_done; last=key; last_id=id; last_prev_entry=prev_entry; } } while(!res.empty()); commit_transaction(); }
void ServerAutomaticArchive::archiveBackups(void) { db_results res_clients=db->Read("SELECT id FROM clients"); for(size_t i=0;i<res_clients.size();++i) { int clientid=watoi(res_clients[i][L"id"]); int r_clientid=clientid; IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid=? AND key=?"); q_get->Bind(clientid); q_get->Bind("overwrite"); db_results res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") r_clientid=0; q_get->Bind(clientid); q_get->Bind("overwrite_archive_settings"); res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") r_clientid=0; bool archive_settings_copied=false; q_get->Bind(clientid); q_get->Bind("archive_settings_copied"); res=q_get->Read(); if(!res.empty() && res[0][L"value"]==L"true") archive_settings_copied=true; if(r_clientid==0 && !archive_settings_copied) { copyArchiveSettings(clientid); } IQuery *q_get_archived=db->Prepare("SELECT id, next_archival, interval, length, backup_types, archive_window FROM settings_db.automatic_archival WHERE clientid=?"); q_get_archived->Bind(clientid); db_results res_archived=q_get_archived->Read(); for(size_t j=0;j<res_archived.size();++j) { _i64 next_archival=watoi64(res_archived[j][L"next_archival"]); std::wstring &archive_window=res_archived[j][L"archive_window"]; _i64 curr_time=Server->getTimeSeconds(); if(next_archival<curr_time && (archive_window.empty() || isInArchiveWindow(archive_window)) ) { int backupid=getNonArchivedFileBackup(watoi(res_archived[j][L"backup_types"]), clientid); if(backupid!=0) { int length=watoi(res_archived[j][L"length"]); archiveFileBackup(backupid, length); Server->Log("Archived file backup with id="+nconvert(backupid)+" for "+nconvert(length)+" seconds", LL_INFO); updateInterval(watoi(res_archived[j][L"id"]), watoi(res_archived[j][L"interval"])); } else { Server->Log("Did not find file backup suitable for archiving with backup_type="+nconvert(watoi(res_archived[j][L"backup_types"])), LL_INFO); } } } } }
bool ServerAutomaticArchive::isInArchiveWindow(const std::wstring &window_def) { std::vector<std::wstring> toks; Tokenize(window_def, toks, L";"); bool matched_dom=false; for(size_t i=0;i<toks.size();++i) { if(trim(toks[i])==L"*") continue; std::vector<std::wstring> stoks; Tokenize(toks[i], stoks, L","); std::vector<int> nums; for(size_t j=0;j<stoks.size();++j) { int n=watoi(stoks[j]); if(i==3)//dow { if(n==7) n=0; } nums.push_back(n); } int ref_num=-1; if(i==0) // hour { ref_num=atoi(os_strftime("%H").c_str()); } else if(i==1) // dom { ref_num=atoi(os_strftime("%d").c_str()); } else if(i==2) // mon { ref_num=atoi(os_strftime("%m").c_str()); } else if(i==3) // dow { ref_num=atoi(os_strftime("%w").c_str()); if(ref_num==7) ref_num=0; } if( std::find(nums.begin(), nums.end(), ref_num)==nums.end() ) { if(i!=1) { if(i==3 && matched_dom==true) continue; return false; } } else { if(i==1) matched_dom=true; } } return true; }
void ServerAutomaticArchive::copyArchiveSettings(int clientid) { db_results res_all=db->Read("SELECT id, next_archival, interval, interval_unit, length, length_unit, backup_types, archive_window FROM settings_db.automatic_archival WHERE clientid=0"); std::vector<std::wstring> next_archivals; for(size_t i=0;i<res_all.size();++i) { std::wstring &interval=res_all[i][L"interval"]; std::wstring &length=res_all[i][L"length"]; std::wstring &backup_types=res_all[i][L"backup_types"]; std::wstring &id=res_all[i][L"id"]; std::wstring &archive_window=res_all[i][L"archive_window"]; std::wstring next_archival=res_all[i][L"next_archival"]; IQuery *q_next=db->Prepare("SELECT next_archival FROM settings_db.automatic_archival WHERE clientid=? AND interval=? AND length=? AND backup_types=? AND archive_window=?"); IQuery *q_num=db->Prepare("SELECT count(*) AS num FROM settings_db.automatic_archival WHERE clientid=0 AND interval=? AND length=? AND backup_types=? AND archive_window=? AND id<?"); q_num->Bind(interval); q_num->Bind(length); q_num->Bind(backup_types); q_num->Bind(archive_window); q_num->Bind(id); db_results res_num=q_num->Read(); int num=watoi(res_num[0][L"num"]); q_next->Bind(clientid); q_next->Bind(interval); q_next->Bind(length); q_next->Bind(backup_types); q_next->Bind(archive_window); db_results res_next=q_next->Read(); if((size_t)num<res_next.size()) { next_archival=res_next[num][L"next_archival"]; _i64 na=watoi64(next_archival); if(na==0) { next_archival=convert(Server->getTimeSeconds()); } } next_archivals.push_back(next_archival); } IQuery *q_del_all=db->Prepare("DELETE FROM settings_db.automatic_archival WHERE clientid=?"); IQuery *q_insert_all=db->Prepare("INSERT INTO settings_db.automatic_archival (next_archival, interval, interval_unit, length, length_unit, backup_types, clientid, archive_window)" "VALUES (?,?,?,?,?,?,?,?)"); q_del_all->Bind(clientid); q_del_all->Write(); for(size_t i=0;i<res_all.size();++i) { std::wstring &interval=res_all[i][L"interval"]; std::wstring &length=res_all[i][L"length"]; std::wstring &backup_types=res_all[i][L"backup_types"]; std::wstring &archive_window=res_all[i][L"archive_window"]; q_insert_all->Bind(next_archivals[i]); q_insert_all->Bind(interval); q_insert_all->Bind(res_all[i][L"interval_unit"]); q_insert_all->Bind(length); q_insert_all->Bind(res_all[i][L"length_unit"]); q_insert_all->Bind(backup_types); q_insert_all->Bind(clientid); q_insert_all->Bind(archive_window); q_insert_all->Write(); q_insert_all->Reset(); } IQuery *q_insert_copied=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES ('archive_settings_copied','true',?)"); q_insert_copied->Bind(clientid); q_insert_copied->Write(); }