/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2009, Tomasz Sowa * All rights reserved. * */ #include "dirs.h" #include "error.h" #include "log.h" #include "db.h" #include "data.h" #include "request.h" void Dirs::Clear() { dir_table.Clear(); } void Dirs::CheckRootDir() { DirContainer::Iterator i = dir_table.GetRoot(); if( i != dir_table.End() ) { if( !request.HasReadExecAccessForRoot(*i) ) { i->privileges = 0755; log << log1 << "Dirs: there is no access for root (admin) to the root dir, setting 0755 for root dir" << logend; db.EditPrivById(*i, i->id); } return; } log << log1 << "Dirs: there is no a root dir in the database (creating one)" << logend; Item root; root.type = Item::dir; root.parent_id = -1; root.user_id = -1; root.group_id = -1; root.privileges = 0755; root.default_item = -1; // !! upewnic sie ze baza nie zmieni url (gdyby wczesniej juz byl w bazie pusty url) // !! zrobic jakis wyjatek do wprowadzania roota? if( db.AddItem(root) == WINIX_ERR_OK ) { dir_table.PushBack(root); } } void Dirs::ReadDirs() { Clear(); db.GetDirs(dir_table); CheckRootDir(); dir_table.FindSpecialFolders(); } bool Dirs::ExtractName(const char * & s, std::string & name) { name.clear(); // skipping first slashes (can be more than one) for( ; *s == '/' ; ++s); for( ; *s != 0 && *s != '/' ; ++s) name += *s; return !name.empty(); } bool Dirs::IsDir(long id) { DirContainer::Iterator i = dir_table.FindId(id); if( i == dir_table.End() ) return false; return true; } bool Dirs::GetDirChilds(long parent, std::vector & childs_table) { if( parent != -1 && !IsDir(parent) ) return false; DirContainer::ParentIterator i = dir_table.FindFirstParent(parent); for( ; i != dir_table.ParentEnd() ; i = dir_table.NextParent(i) ) childs_table.push_back( &(*i->second) ); return true; } DirContainer::ParentIterator Dirs::FindFirstParent(long parent_id) { DirContainer::ParentIterator i = dir_table.FindFirstParent(parent_id); return i; } DirContainer::ParentIterator Dirs::NextParent(DirContainer::ParentIterator i) { return dir_table.NextParent(i); } DirContainer::ParentIterator Dirs::ParentEnd() { return dir_table.ParentEnd(); } // dodatkowo moze metoda AppendPath dodajaca sciezke do biezacego stringa? // albo tutaj stringa nie czyscic? // O(m * log n) (m- how many parts are in 'id') bool Dirs::MakePath(long id, std::string & path) { DirContainer::Iterator i; path = '/'; while( true ) { i = dir_table.FindId(id); if( i == dir_table.End() ) return false; if( i->parent_id == -1 ) return true; id = i->parent_id; path.insert(0, i->url); path.insert(path.begin(), '/'); } } Item * Dirs::GetRootDir() { DirContainer::Iterator root = dir_table.GetRoot(); if( root == dir_table.End() ) return 0; return &(*root); } Item * Dirs::GetEtcDir() { DirContainer::Iterator etc = dir_table.GetEtc(); if( etc == dir_table.End() ) return 0; return &(*etc); } Item * Dirs::GetDir(const std::string & name, long parent) { DirContainer::ParentIterator i = dir_table.FindFirstParent(parent); for( ; i!=dir_table.ParentEnd() ; i = dir_table.NextParent(i) ) if( i->second->url == name ) return &(*i->second); return 0; } Item * Dirs::GetDir(const std::string & path) { DirContainer::Iterator root = dir_table.GetRoot(); if( root == dir_table.End() ) // ops, we do not have a root dir return 0; Item * pitem = &(*root); std::string name; const char * s = path.c_str(); while( ExtractName(s, name) ) { pitem = GetDir(name, pitem->id); if( !pitem ) return 0; } return pitem; } Item * Dirs::GetDir(long id) { DirContainer::Iterator i = dir_table.FindId(id); if( i == dir_table.End() ) return 0; return &(*i); } Item * Dirs::AddDir(const Item & item) { return &(*dir_table.PushBack(item)); } void Dirs::SplitPath(const std::string & path, std::string & dir, std::string & file) { std::string::size_type i; dir.clear(); file.clear(); if( path.empty() ) // !! moze dir ustawic na '/' ? return; for( i=path.size()-1 ; i>0 && path[i]!='/' ; --i); if( path[i] != '/' ) { // we do not have any slashes '/' file = path; return; } dir.assign(path, 0, i + 1); // +1 means with a slash at the end if( i < path.size() - 1 ) file.assign(path, i+1, path.size() - i - 1); } // !! przeniesc to do rm // mamy juz interfejs do chodzenia po parentach void Dirs::DeleteDir(long id) { DirContainer::ParentIterator pnext, p = dir_table.FindFirstParent(id); for( ; p != dir_table.ParentEnd() ; p = pnext ) { // this iterator p will be deleted by the next DeleteDir(p->second->id) // (the next iterator we must calculate beforehand) pnext = dir_table.NextParent(p); DeleteDir(p->second->id); } if( db.DelDirById(id) == WINIX_ERR_OK ) dir_table.DelById(id); db.RemoveThread(id); db.RemoveTicket(id); }