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; }
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; }
_i64 ChangeJournalWatcher::hasEntry( _i64 rid, _i64 frn) { q_get_entry->Bind(frn); q_get_entry->Bind(rid); db_results res=q_get_entry->Read(); q_get_entry->Reset(); if(res.empty()) return -1; else return os_atoi64(wnarrow(res[0][L"id"])); }
_i64 ChangeJournalWatcher::hasRoot(const std::wstring &root) { q_has_root->Bind(root); db_results res=q_has_root->Read(); q_has_root->Reset(); if(res.empty()) return -1; else { return os_atoi64(wnarrow(res[0][L"id"])); } }
std::vector<_i64 > ChangeJournalWatcher::getChildren(_i64 frn, _i64 rid) { std::vector<_i64> ret; q_get_children->Bind(frn); q_get_children->Bind(rid); db_results res=q_get_children->Read(); q_get_children->Reset(); for(size_t i=0;i<res.size();++i) { ret.push_back(os_atoi64(wnarrow(res[i][L"frn"]))); } return ret; }
std::vector<UsnInt> ChangeJournalWatcher::getJournalData(const std::wstring &vol) { q_get_journal_data->Bind(vol); db_results res=q_get_journal_data->Read(); q_get_journal_data->Reset(); std::vector<UsnInt> ret; for(size_t i=0;i<res.size();++i) { UsnInt rec; rec.Usn=os_atoi64(wnarrow(res[i][L"usn"])); rec.Reason=(DWORD)os_atoi64(wnarrow(res[i][L"reason"])); rec.Filename=res[i][L"filename"]; rec.FileReferenceNumber=os_atoi64(wnarrow(res[i][L"frn"])); rec.ParentFileReferenceNumber=os_atoi64(wnarrow(res[i][L"parent_frn"])); rec.NextUsn=os_atoi64(wnarrow(res[i][L"next_usn"])); rec.attributes=(DWORD)os_atoi64(wnarrow(res[i][L"attributes"])); ret.push_back(rec); } return ret; }
bool TreeReader::readTree(const std::string &fn) { std::fstream in; in.open(fn.c_str(), std::ios::in | std::ios::binary ); if (!in.is_open()) { Log("Cannot read file tree from file \"" + fn + "\""); return false; } size_t read; char buffer[buffer_size]; int state=0; size_t lines=0; size_t stringbuffer_size=0; std::string name; char ltype=0; do { in.read(buffer, buffer_size); read=(size_t)in.gcount(); for(size_t i=0;i<read;++i) { const char ch=buffer[i]; switch(state) { case 0: if(ch=='f' || ch=='d') { ltype = ch; state = 1; } else if(ch=='u') { state = 10; ltype = 'd'; name = ".."; } else { Log("Error parsing file readTree - 0. Expected 'f', 'd', or 'u'. Got '"+std::string(1, ch)+"' at line "+convert(lines)+" while reading "+fn); return false; } break; case 1: //" state=2; break; case 2: if(ch=='"') { state=3; } else if(ch=='\\') { state=5; } else { name+=ch; } break; case 5: if(ch!='\"' && ch!='\\') { name+='\\'; } name+=ch; state=2; break; case 3: if(ch==' ') { state=4; break; } else { state=10; } case 4: if(state==4) { if(ch!='\n') { break; } } case 10: if(ch=='\n') { state=0; if(ltype=='f') { stringbuffer_size+=2*sizeof(int64); } if(ltype!='d' || name!="..") { if(ltype=='d') { stringbuffer_size+=sizeof(int64); } ++lines; stringbuffer_size+=name.size()+1; } name.clear(); ltype=0; } } } } while(read>0); in.clear(); name.clear(); in.seekg(0, std::ios::beg); size_t stringbuffer_pos=0; stringbuffer.resize(stringbuffer_size+5); state=0; bool isdir=false; std::string data; std::stack<TreeNode*> parents; std::stack<TreeNode*> lastNodes; bool firstChild=true; size_t idx=1; nodes.resize(lines+1); std::string root_str = "root"; memcpy(&stringbuffer[0], root_str.c_str(), root_str.size()+1); stringbuffer_pos+=root_str.size()+1; nodes[0].setName(&stringbuffer[0]); parents.push(&nodes[0]); lastNodes.push(&nodes[0]); lines=0; do { in.read(buffer, buffer_size); read=(size_t)in.gcount(); for(size_t i=0;i<read;++i) { const char ch=buffer[i]; switch(state) { case 0: if(ch=='f') { data+='f'; state=1; } else if(ch=='d') { data+='d'; state=1; } else if(ch=='u') { name=".."; state=10; } else { Log("Error parsing file readTree - 1. Expected 'f', 'd', or 'u'. Got '" + std::string(1, ch) + "' at line " + convert(lines)+" while reading "+fn); return false; } break; case 1: //" state=2; break; case 2: if(ch=='"') { state=3; } else if(ch=='\\') { state=5; } else { name+=ch; } break; case 5: if(ch!='\"' && ch!='\\') { name+='\\'; } name+=ch; state=2; break; case 3: if(ch==' ') { state=4; break; } else { state=10; } case 4: if(state==4) { if(ch!='\n') { data+=ch; break; } } case 10: if(ch=='\n') { if(name!="..") { memcpy(&stringbuffer[stringbuffer_pos], name.c_str(), name.size()+1); nodes[idx].setName(&stringbuffer[stringbuffer_pos]); stringbuffer_pos+=name.size()+1; nodes[idx].setId(lines); char ch=data[0]; nodes[idx].setType(ch); if(ch=='f') { std::string sdata=data.substr(1); std::string filesize=getuntil(" ", sdata); std::string last_mod=getafter(" ", sdata); _i64 ifilesize=os_atoi64(filesize); _i64 ilast_mod=os_atoi64(last_mod); char* ndata=&stringbuffer[stringbuffer_pos]; memcpy(&stringbuffer[stringbuffer_pos], &ifilesize, sizeof(_i64)); stringbuffer_pos+=sizeof(_i64); memcpy(&stringbuffer[stringbuffer_pos], &ilast_mod, sizeof(_i64)); stringbuffer_pos+=sizeof(_i64); nodes[idx].setData(ndata); } else { std::string sdata=data.substr(1); std::string last_mod=getafter(" ", sdata); _i64 ilast_mod=os_atoi64(last_mod); char* ndata=&stringbuffer[stringbuffer_pos]; memcpy(&stringbuffer[stringbuffer_pos], &ilast_mod, sizeof(_i64)); stringbuffer_pos+=sizeof(_i64); nodes[idx].setData(ndata); } if(firstChild) { lastNodes.push(&nodes[idx]); firstChild=false; } else { lastNodes.top()->setNextSibling(&nodes[idx]); lastNodes.pop(); lastNodes.push(&nodes[idx]); } if(!parents.empty()) { parents.top()->incrementNumChildren(); nodes[idx].setParent(parents.top()); } if(ch=='d') { parents.push(&nodes[idx]); firstChild=true; } ++idx; } else { if(!parents.empty()) { parents.pop(); } else { Log("TreeReader: parents empty"); return false; } if(!firstChild) { if(lastNodes.empty()) { Log("TreeReader: lastNodes empty"); return false; } lastNodes.top()->setNextSibling(NULL); lastNodes.pop(); } firstChild=false; } name.clear(); data.clear(); state=0; ++lines; } } } } while(read==buffer_size); assert(idx == nodes.size()); assert(stringbuffer_pos == stringbuffer.size()); nodes[0].setNextSibling(NULL); return true; }