bool DeleteListRecursively( FS* fs, FSPath path, FSList& list ) { const int cnt = path.Count(); int ret_err; for ( FSNode* node = list.First(); node; node = node->next ) { if ( node->extType ) { continue; } path.SetItemStr( cnt, node->Name() ); if ( node->IsDir() && !node->st.IsLnk() ) { if ( !DeleteDirRecursively( fs, path ) ) { return false; } } else if ( fs->Delete( path, &ret_err, nullptr ) != 0 ) { return false; } } return true; }
bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) { if (node.getChild(packName + ".xml").exists()) { _fileArchive = new FSDirectory(node, 1); // uncompressed keyboard pack if (!_parser->loadFile(node.getChild(packName + ".xml"))) { delete _fileArchive; _fileArchive = 0; return false; } return true; } if (node.getChild(packName + ".zip").exists()) { // compressed keyboard pack _fileArchive = makeZipArchive(node.getChild(packName + ".zip")); if (_fileArchive && _fileArchive->hasFile(packName + ".xml")) { if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml"))) { delete _fileArchive; _fileArchive = 0; return false; } } else { warning("Could not find %s.xml file in %s.zip keyboard pack", packName.c_str(), packName.c_str()); delete _fileArchive; _fileArchive = 0; return false; } return true; } return false; }
bool FSDirectory::hasFile(const String &name) const { if (name.empty() || !_node.isDirectory()) return false; FSNode *node = lookupCache(_fileCache, name); return node && node->exists(); }
bool OperCFThread::DeleteList( FS* fs, FSPath& _path, FSList& list ) { if ( Info()->Stopped() ) { return false; } FSPath path = _path; int cnt = path.Count(); for ( FSNode* node = list.First(); node; node = node->next ) { if ( node->extType ) { continue; } path.SetItemStr( cnt, node->Name() ); if ( node->IsDir() && !node->st.IsLnk() ) { if ( !DeleteDir( fs, path ) ) { return false; } if ( !RmDir( fs, path ) ) { return false; } continue; } if ( !DeleteFile( fs, path ) ) { return false; } } return true; }
void PanelList::MakeList() { listCount = 0; list.clear(); filesCn.Clear(); selectedCn.Clear(); hiddenCn.Clear(); if (data.ptr() && data->Count()>0) { int n = data->Count(); list.alloc(n); int i = 0; for (FSNode *p = data->First(); p && i < n; p = p->next) if (showHidden || !p->IsHidden()) { list[ i++ ] = p; filesCn.AddOne(p->st.size); if (p->IsSelected()) selectedCn.AddOne(p->st.size); } else { p->ClearSelected(); hiddenCn.AddOne(p->st.size); } listCount = i; } }
u32int FSNode::scall(u8int wat, u32int a, u32int b, u32int c, u32int d) { if (wat == FNIF_SGETRFN) return VFS::getRootNode()->resId(); if (wat == FNIF_SGETCWD) return Task::currProcess()->getCwd()->resId(); if (wat == FNIF_SFIND) { String* path = (String*)a; FSNode* n; if (b == 0) { n = VFS::find(*path); } else { n = VFS::find(*path, Res::get<DirectoryNode>(b, FNIF_OBJTYPE)); } if (n != 0) return n->resId(); } if (wat == FNIF_SMKDIR) { String* path = (String*)a; FSNode* n; if (b == 0) { n = VFS::createDirectory(*path, 0, true); } else { n = VFS::createDirectory(*path, Res::get<DirectoryNode>(b, FNIF_OBJTYPE), true); } if (n != 0) return n->resId(); } return (u32int) - 1; }
bool OperCFThread::Copy(FS *srcFs, FSPath &__srcPath, FSList *list, FS *destFs, FSPath &__destPath, cstrhash<bool,unicode_t> &resList) { if (list->Count()<=0) return true; FSPath srcPath = __srcPath; int srcPos = srcPath.Count(); FSPath destPath = __destPath; int destPos = destPath.Count(); FSStat st; int ret_error; int res = destFs->Stat(__destPath, &st, &ret_error, Info()); if (res == -2) return false; if (res && !destFs->IsENOENT(ret_error)) { RedMessage( _LT("Can't copy to:\n"), destFs->Uri(destPath).GetUtf8(), bOk, destFs->StrError(ret_error).GetUtf8()); return false; } bool exist = (res == 0); if (list->Count()>1) { //если файлов >1 то копировать можно только в каталог if (!exist) { RedMessage( _LT("Can't copy files, destination is not found:\n"), destFs->Uri(__destPath).GetUtf8(), bOk); return false; } if (!st.IsDir()) { RedMessage( _LT("Destination is not directory:\n"), destFs->Uri(__destPath).GetUtf8(), bOk); return false; } for (FSNode *node = list->First(); node; node = node->next) { if (Info()->Stopped()) return false; srcPath.SetItemStr(srcPos, node->Name()); destPath.SetItemStr(destPos, node->Name()); if (!CopyNode(srcFs, srcPath, node, destFs, destPath, false)) return false; resList[node->Name().GetUnicode()] = true; } } else { // 1 element if (exist && st.IsDir()) destPath.SetItemStr(destPos, list->First()->Name()); srcPath.SetItemStr(srcPos, list->First()->Name()); if (!CopyNode(srcFs, srcPath, list->First(), destFs, destPath, false)) return false; resList[list->First()->Name().GetUnicode()] = true; }; return true; }
bool XMLParser::loadFile(const FSNode &node) { _stream = node.createReadStream(); if (!_stream) return false; _fileName = node.getName(); return true; }
bool OperCFThread::Move(FS *srcFs, FSPath &__srcPath, FSList *list, FS *destFs, FSPath &__destPath) { if (list->Count()<=0) return true; FSPath srcPath = __srcPath; int srcPos = srcPath.Count(); FSPath destPath = __destPath; int destPos = destPath.Count(); FSStat st; int ret_error; int r = destFs->Stat(__destPath, &st, &ret_error, Info()); if (r == -2) return false; if (list->Count()>1) { //если файлов >1 то копировать можно только в каталог if (r) { RedMessage( _LT("Can't move files, bad destination directory:\n"), destFs->Uri(__destPath).GetUtf8(), bOk, destFs->StrError(ret_error).GetUtf8()); return false; } if (!st.IsDir()) { RedMessage( _LT("Destination is not directory:\n"), destFs->Uri(__destPath).GetUtf8(), bOk); return false; } for (FSNode *node = list->First(); node; node = node->next) { srcPath.SetItemStr(srcPos, node->Name()); destPath.SetItemStr(destPos, node->Name()); //printf("MOVE '%s'\n", srcPath.GetUtf8()); if (!MoveNode(srcFs, srcPath, node, destFs, destPath)) return false; } } else { // 1 element if (r && !destFs->IsENOENT(ret_error)) { RedMessage( _LT("Can't move to:\n"), destFs->Uri(destPath).GetUtf8(), bOk, destFs->StrError(ret_error).GetUtf8()); return false; } if (!r && st.IsDir()) destPath.SetItemStr(destPos, list->First()->Name()); FSNode *node = list->First(); srcPath.SetItemStr(srcPos, list->First()->Name()); if (!MoveNode(srcFs, srcPath, list->First(), destFs, destPath)) return false; } return true; }
bool FSNode::operator<(const FSNode& node) const { // Directories come before files, i.e., are "lower". if (isDirectory() != node.isDirectory()) return isDirectory(); // If both nodes are of the same type (two files or two dirs), // then sort by name, ignoring case. return getDisplayName().compareToIgnoreCase(node.getDisplayName()) < 0; }
bool TranslationManager::openTranslationsFile(const FSNode &node, File &inFile, int depth) { if (!node.exists() || !node.isReadable() || !node.isDirectory()) return false; // Check if we can find the file in this directory // Since File::open(FSNode) makes all the needed tests, it is not really // necessary to make them here. But it avoid printing warnings. FSNode fileNode = node.getChild("translations.dat"); if (fileNode.exists() && fileNode.isReadable() && !fileNode.isDirectory()) { if (inFile.open(fileNode)) { if (checkHeader(inFile)) return true; inFile.close(); } } // Check if we exceeded the given recursion depth if (depth - 1 == -1) return false; // Otherwise look for it in sub-directories FSList fileList; if (!node.getChildren(fileList, FSNode::kListDirectoriesOnly)) return false; for (FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) { if (openTranslationsFile(*i, inFile, depth == -1 ? - 1 : depth - 1)) return true; } // Not found in this directory or its sub-directories return false; }
SeekableReadStream *FSDirectory::createReadStreamForMember(const String &name) const { if (name.empty() || !_node.isDirectory()) return 0; FSNode *node = lookupCache(_fileCache, name); if (!node) return 0; SeekableReadStream *stream = node->createReadStream(); if (!stream) warning("FSDirectory::createReadStreamForMember: Can't create stream for file '%s'", name.c_str()); return stream; }
bool DumpFile::open(const FSNode &node) { assert(!_handle); if (node.isDirectory()) { warning("DumpFile::open: FSNode is a directory"); return false; } _handle = node.createWriteStream(); if (_handle == nullptr) debug(2, "File %s not found", node.getName().c_str()); return _handle != nullptr; }
void OperDirCalcThread::Calc() { MutexLock lock( Node().GetMutex() ); if ( !Node().Data() ) { return; } OperDirCalcData* CalcData = ( OperDirCalcData* )Node().Data(); clPtr<FS> fs = CalcData->dirFs; FSPath path = CalcData->_path; clPtr<FSList> list = CalcData->dirList; lock.Unlock(); //!!! //dbg_printf("OperDirCalcThread::Calc list data:"); //path.dbg_printf("FSPath:"); //for (FSNode* node = list->First(); node; node = node->next) // dbg_printf("%s\n", node->name.GetUtf8()); if (list->Count() == 0) { // then calculate current dir size CalcDir(fs.Ptr(), path); } else { // list is not empty: calculate size of objects in the list int cnt = path.Count(); for (FSNode* node = list->First(); node; node = node->next) { path.SetItemStr(cnt, node->Name()); //-V595 bool IsDir = node->IsDir() && !node->st.IsLnk(); if ( IsDir ) { int64_t Size = CalcDir( fs.Ptr(), path); if ( Size >= 0 && node && node->originNode ) { node->originNode->st.size = Size; } CalcData->folderCount++; } else { CalcData->fileCount++; CalcData->sumSize += node->st.size; } } } }
const ArchiveMemberPtr FSDirectory::getMember(const String &name) const { if (name.empty() || !_node.isDirectory()) return ArchiveMemberPtr(); FSNode *node = lookupCache(_fileCache, name); if (!node || !node->exists()) { warning("FSDirectory::getMember: '%s' does not exist", name.c_str()); return ArchiveMemberPtr(); } else if (node->isDirectory()) { warning("FSDirectory::getMember: '%s' is a directory", name.c_str()); return ArchiveMemberPtr(); } return ArchiveMemberPtr(new FSNode(*node)); }
bool OperCFThread::CopyDir(FS *srcFs, FSPath &__srcPath, FSNode *srcNode, FS *destFs, FSPath &__destPath, bool move) { if (Info()->Stopped()) return false; FSList list; int ret_error; while (true) { int ret = srcFs->ReadDir(&list, __srcPath, &ret_error, Info()); if (ret == -2) return false; if (!ret) break; switch ( RedMessage( _LT("Can`t open directory:\n") , srcFs->Uri(__srcPath).GetUtf8(), bRetrySkipCancel, srcFs->StrError(ret_error).GetUtf8()) ) { case CMD_SKIP: return true; case CMD_RETRY: continue; default: return false; } } while (destFs->MkDir(__destPath, MkDirMode, &ret_error, Info()) && !destFs->IsEEXIST(ret_error)) { switch (RedMessage( _LT("Can't create the directory:\n"), destFs->Uri(__destPath).GetUtf8(), bRetrySkipCancel, destFs->StrError(ret_error).GetUtf8())) { case CMD_CANCEL: return false; case CMD_SKIP: return true; } } FSPath srcPath = __srcPath; int srcPos = srcPath.Count(); FSPath destPath = __destPath; int destPos = destPath.Count(); for (FSNode *node = list.First(); node; node = node->next) { if (Info()->Stopped()) return false; srcPath.SetItemStr(srcPos, node->Name()); destPath.SetItemStr(destPos, node->Name()); if (!CopyNode(srcFs, srcPath, node, destFs, destPath, move)) return false; } destFs->SetFileTime(destPath, srcNode->st.mtime, srcNode->st.mtime, 0, Info()); return !move || RmDir(srcFs, __srcPath); }
std::vector<FSNode*> FSList::GetFilteredArray( bool showHidden, int* pCount ) { if ( pCount ) { *pCount = 0; } std::vector<FSNode*> p( Count() ); FSNode* pNode = first; int n = Count(); int i; for ( i = 0 ; i < n && pNode; pNode = pNode->next ) if ( showHidden || !pNode->IsHidden() ) { p[i++] = pNode; } if ( pCount ) { *pCount = i; } return p; }
void PanelList::Mark( const unicode_t* mask, bool enable ) { int n = listCount; PanelCounter counter; for ( int i = 0; i < n; i++ ) { FSNode* p = list[i]; if ( !p ) { continue; } bool ok = accmask( p->GetUnicodeName(), mask ); if ( ok ) { if ( enable ) { p->SetSelected(); } else { p->ClearSelected(); } } if ( p->IsSelected() ) { counter.AddOne( p->Size() ); } } selectedCn = counter; }
/************************************************* * Description: Loads the directoy contents of ~/Documents/Pictures into listview * Author: Rick Caudill * Date: Thu Mar 18 20:17:32 2004 **************************************************/ void WallpaperChangerSettings::LoadDirectoryList() { String cDir = getenv( "HOME" ); cDir += "/Pictures/"; String cFile; Directory* pcDir = new Directory(cDir); pcDir->Rewind(); while (pcDir->GetNextEntry(&cFile)) { FSNode* pcNode = new FSNode(String(cDir + cFile)); if (pcNode->IsFile()) //if not a dir, link and just a regular file { ListViewStringRow* pcRow = new ListViewStringRow(); pcRow->AppendString(cFile); pcDirectoryList->InsertRow(pcRow); } delete pcNode; } delete pcDir; }
void PanelList::InvertSelection() { int n = listCount; selectedCn.Clear(); for ( int i = 0; i < n; i++ ) { FSNode* p = list.data()[i]; if ( p->IsSelected() ) { p->ClearSelected(); } else { if ( !wcmConfig.panelSelectFolders && p->IsDir() ) { continue; } p->SetSelected(); selectedCn.AddOne( p->st.size ); } } };
int FSNode::CmpByExt( FSNode& a, bool case_sensitive ) { const unicode_t* s1 = unicode_rchr( GetUnicodeName(), '.' ); const unicode_t* s2 = unicode_rchr( a.GetUnicodeName(), '.' ); if ( s1 ) return ( s2 ) ? ( case_sensitive ? CmpStr<const unicode_t>( s1, s2 ) : CmpNoCase( s1, s2 ) ) : 1; else { return s2 ? -1 : 0; } }
void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority) { FSList subDirs; if (!directory.getChildren(subDirs)) return; String nextPattern, pattern; String::const_iterator sep = Common::find(origPattern.begin(), origPattern.end(), '/'); if (sep != origPattern.end()) { pattern = String(origPattern.begin(), sep); ++sep; if (sep != origPattern.end()) nextPattern = String(sep, origPattern.end()); } else { pattern = origPattern; } // TODO: The code we have for displaying all matches, which vary only in case, might // be a bit overhead, but as long as we want to display all useful information to the // user we will need to keep track of all directory names added so far. We might // want to reconsider this though. typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> MatchList; MatchList multipleMatches; MatchList::iterator matchIter; for (FSList::const_iterator i = subDirs.begin(); i != subDirs.end(); ++i) { String name = i->getName(); if (Common::matchString(name.c_str(), pattern.c_str(), ignoreCase)) { matchIter = multipleMatches.find(name); if (matchIter == multipleMatches.end()) { multipleMatches[name] = true; } else { if (matchIter->_value) { warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), matchIter->_key.c_str()); matchIter->_value = false; } warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), name.c_str()); } if (nextPattern.empty()) addDirectory(name, *i, priority); else addSubDirectoriesMatching(*i, nextPattern, ignoreCase, priority); } } }
bool FileAttributesDlg( NCDialogParent* Parent, PanelWin* Panel ) { clFileAttributesWin Dialog( Parent, Panel ); if ( Dialog.DoModal( ) == CMD_OK ) { FSNode* Node = Dialog.GetNode(); // apply changes if ( Node ) { FSPath fspath; FSString URI = Dialog.GetURI(); clPtr<FS> fs = ParzeURI( URI.GetUnicode(), fspath, {} ); if ( fs ) { int Err = 0; FSCInfo Info; fs->StatSetAttr( fspath, &Node->st, &Err, &Info ); if ( Err != 0 ) { throw_msg( "Error setting file attributes: %s", fs->StrError( Err ).GetUtf8() ); } fs->SetFileTime( fspath, Node->GetCreationTime(), Node->GetLastAccessTime(), Node->GetLastWriteTime(), &Err, &Info ); if ( Err != 0 ) { throw_msg("Error setting file date & time: %s", fs->StrError(Err).GetUtf8()); } } } return true; } return false; }
bool File::open(const FSNode &node) { assert(!_handle); if (!node.exists()) { warning("File::open: '%s' does not exist", node.getPath().c_str()); return false; } else if (node.isDirectory()) { warning("File::open: '%s' is a directory", node.getPath().c_str()); return false; } SeekableReadStream *stream = node.createReadStream(); return open(stream, node.getPath()); }
void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) const { if (depth <= 0) return; FSList list; node.getChildren(list, FSNode::kListAll, true); FSList::iterator it = list.begin(); for ( ; it != list.end(); ++it) { String name = prefix + it->getName(); // don't touch name as it might be used for warning messages String lowercaseName = name; lowercaseName.toLowercase(); // since the hashmap is case insensitive, we need to check for clashes when caching if (it->isDirectory()) { if (!_flat && _subDirCache.contains(lowercaseName)) { warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str()); } else { if (_subDirCache.contains(lowercaseName)) { warning("FSDirectory::cacheDirectory: name clash when building subDirCache with subdirectory '%s'", name.c_str()); } cacheDirectoryRecursive(*it, depth - 1, _flat ? prefix : lowercaseName + "/"); _subDirCache[lowercaseName] = *it; } } else { if (_fileCache.contains(lowercaseName)) { warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'", name.c_str()); } else { _fileCache[lowercaseName] = *it; } } } }
void PanelList::ShiftSelection( int n, int* selectType, bool RootDir ) { FSNode* p = NULL; if ( RootDir ) { if ( n < 0 || n >= listCount ) { return; } p = list[n]; } else { if ( n <= 0 || n > listCount ) { return; } p = list[n - 1]; } if ( !p ) { return; } if ( *selectType < 0 ) //not defined { *selectType = p->IsSelected() ? 0 : 1; } bool sel = ( *selectType > 0 ); if ( sel == p->IsSelected() ) { return; } if ( sel ) { p->SetSelected(); selectedCn.AddOne( p->Size() ); } else { p->ClearSelected(); selectedCn.SubOne( p->Size() ); } }
void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority, int depth, bool flat) { if (!dir.exists() || !dir.isDirectory()) return; add(name, new FSDirectory(dir, depth, flat), priority); }
int OperCFThread::MoveDir( FS* srcFs, FSPath& __srcPath, FSNode* srcNode, FS* destFs, FSPath& __destPath ) { if ( Info()->Stopped() ) { return -1; } if ( srcFs != destFs ) { return 1; } FSPath srcPath = __srcPath; int srcPos = srcPath.Count(); FSPath destPath = __destPath; int destPos = destPath.Count(); if ( IsSameFile( srcFs, srcPath, &( srcNode->st ), destFs, destPath ) ) { RedMessage( _LT( "Can't move directory to itself:\n" ), srcFs->Uri( __srcPath ).GetUtf8() ); return -1; } FSStat st; int ret_error; if ( !destFs->Stat( destPath, &st, &ret_error, Info() ) ) { if ( !st.IsDir() ) { switch ( RedMessage( _LT( "Can't copy directory\n" ), srcFs->Uri( srcPath ).GetUtf8(), _LT( "to file" ), "\n", _LT( "Delete the file?" ), destFs->Uri( destPath ).GetUtf8(), bOkSkipCancel ) ) { case CMD_CANCEL: return -1; case CMD_SKIP: return 0; } if ( !Unlink( destFs, destPath ) ) { return -1; } } else { FSList list; while ( true ) { int ret = srcFs->ReadDir( &list, srcPath, &ret_error, Info() ); if ( ret == -2 ) { return -1; } if ( !ret ) { break; } switch ( RedMessage( _LT( "Can`t open directory:\n" ), srcFs->Uri( __srcPath ).GetUtf8(), bRetrySkipCancel, srcFs->StrError( ret_error ).GetUtf8() ) ) { case CMD_SKIP: return 0; case CMD_RETRY: continue; default: return -1; } } for ( FSNode* node = list.First(); node; node = node->next ) { if ( Info()->Stopped() ) { return -1; } srcPath.SetItemStr( srcPos, node->Name() ); destPath.SetItemStr( destPos, node->Name() ); if ( !MoveFile( srcFs, srcPath, node, destFs, destPath ) ) { return -1; } } destFs->SetFileTime( destPath, srcNode->st.m_CreationTime, srcNode->st.m_LastWriteTime, srcNode->st.m_LastWriteTime, 0, Info() ); return RmDir( srcFs, srcPath ) ? 0 : -1; } } if ( srcFs->Rename( srcPath, destPath, &ret_error, Info() ) ) { if ( srcFs->IsEXDEV( ret_error ) ) { return 1; } return RedMessage( _LT( "Can't rename the directory:\n" ), srcFs->Uri( srcPath ).GetUtf8(), "\nto\n", destFs->Uri( destPath ).GetUtf8(), bSkipCancel, srcFs->StrError( ret_error ).GetUtf8() ) == CMD_SKIP ? 0 : -1; } return 0; }
int main(int argc, char* argv[]) { FileSystem rootfs; rootfs.addNode("/", new FSDir("dayos", VFS_MODE_RW)); rootfs.addNode("/", new FSDir("drives", VFS_MODE_RW)); rootfs.addNode("/dayos", new FSDir("dev", VFS_MODE_RW)); if (register_service("vfs") != SIGNAL_OK) { debug_printf("[ VFS ] Could not register VFS service. Will terminate.\n"); return -1; } pid_t vfs_pid = get_service_pid("vfs"); message_t msg; struct vfs_request* request = (struct vfs_request*)&msg.message; while (1) { while (receive_message(&msg, MESSAGE_ANY) != MESSAGE_RECEIVED) sleep(10); switch (msg.signal) { case VFS_SIGNAL_CREATE_DEVICE: if (!rootfs.mkdev(request->path, (VFS_OPEN_MODES)request->mode, (DEVICE_TYPES)request->param, msg.sender)) msg.signal = SIGNAL_FAIL; else msg.signal = SIGNAL_OK; send_message(&msg, msg.sender); break; case VFS_SIGNAL_MOUNT_DEVICE: { struct vfs_request req = *request; if (receive_message_timeout(&msg, msg.sender, 100, 10) != MESSAGE_RECEIVED) break; if (!rootfs.mount(req.path, request->path, (VFS_OPEN_MODES)req.mode, request->param)) msg.signal = SIGNAL_FAIL; else msg.signal = SIGNAL_OK; send_message(&msg, msg.sender); } break; case VFS_SIGNAL_MOUNT_RAMDISK: { if (!rootfs.mount(request->path, (VFS_OPEN_MODES)request->mode, msg.sender)) msg.signal = SIGNAL_FAIL; else msg.signal = SIGNAL_OK; send_message(&msg, msg.sender); } break; case VFS_SIGNAL_OPEN: { pid_t sender = msg.sender; FSNode* node = rootfs.findNode(request->path); struct vfs_file* file = (struct vfs_file*)&msg.message; if (!node) { msg.signal = SIGNAL_FAIL; send_message(&msg, msg.sender); break; } msg.signal = SIGNAL_OK; switch (node->getType()) { case NODE_DEVICE: { FSDevice* dev = static_cast<FSDevice*>(node); file->device = dev->getDriverPID(); file->type = dev->getDeviceType(); file->uid = dev->getUID(); file->guid = dev->getGUID(); strcpy(file->path, request->path); } break; case NODE_MOUNT: { FSMount* mount = static_cast<FSMount*>(node); file->device = mount->getFilesystemDriver(); file->type = VFS_MOUNTPOINT; // FIXME: Fetch from FS driver! file->uid = mount->getUID(); file->guid = mount->getGUID(); std::string path; path = request->path; path = path.substr(strlen(mount->getPath())); strcpy(file->path, path.c_str()); } break; default: msg.signal = SIGNAL_FAIL; } send_message(&msg, sender); } break; case VFS_SIGNAL_OPEN_DIR: { pid_t sender = msg.sender; FSNode* node = rootfs.findNode(request->path); struct vfs_file* file = (struct vfs_file*) &msg.message; if (!node || (node->getType() != NODE_MOUNT && node->getType() != NODE_DIR)) { msg.signal = SIGNAL_FAIL; send_message(&msg, msg.sender); break; } msg.signal = SIGNAL_OK; switch (node->getType()) { case NODE_DIR: { FSDir* dir = static_cast<FSDir*>(node); file->type = VFS_DIRECTORY; file->uid = dir->getUID(); file->guid = dir->getGUID(); file->nid = dir->getNodeId(); file->child_nid = 0; file->device = vfs_pid; file->offset = 0; strcpy(file->path, request->path); } break; case NODE_MOUNT: { FSMount* mount = static_cast<FSMount*>(node); file->device = mount->getFilesystemDriver(); file->type = VFS_MOUNTPOINT; // FIXME: Fetch from FS driver! file->uid = mount->getUID(); file->guid = mount->getGUID(); std::string path; path = request->path; path = path.substr(strlen(mount->getPath())); if(path.empty()) path = "/"; strcpy(file->path, path.c_str()); } break; } send_message(&msg, sender); } break; case VFS_SIGNAL_READ_DIR: { pid_t sender = msg.sender; FSNode* node = rootfs.findNode(request->path); struct vfs_file* file = (struct vfs_file*) &msg.message; if (!node || (node->getType() != NODE_MOUNT && node->getType() != NODE_DIR)) { msg.signal = SIGNAL_FAIL; send_message(&msg, msg.sender); break; } msg.signal = SIGNAL_OK; switch (node->getType()) { case NODE_DIR: { FSDir* dir = static_cast<FSDir*>(node); unsigned int next_item = request->param + 1; node = dir->getChild(request->param); if(!node) { msg.signal = SIGNAL_FAIL; break; } file->type = node->getType(); file->uid = node->getUID(); file->guid = node->getGUID(); file->child_nid = next_item; file->nid = node->getNodeId(); strcpy(file->path, node->getName()); } break; case NODE_MOUNT: { FSMount* mount = static_cast<FSMount*>(node); file->device = mount->getFilesystemDriver(); file->type = VFS_MOUNTPOINT; // FIXME: Fetch from FS driver! file->uid = mount->getUID(); file->guid = mount->getGUID(); file->nid = node->getNodeId(); std::string path; path = request->path; path = path.substr(strlen(mount->getPath())); strcpy(file->path, path.c_str()); } break; } send_message(&msg, sender); } break; case VFS_SIGNAL_CREATE_DIRECTORY: { pid_t sender = msg.sender; FSNode* node = rootfs.findNode(request->path); struct vfs_file* file = (struct vfs_file*) &msg.message; msg.signal = SIGNAL_FAIL; if (!node) { std::string path = request->path; int idx = path.find_last_of('/'); if(idx != -1) { path.erase(idx); rootfs.addNode((idx == 0) ? "/" : path.c_str(), new FSDir(&request->path[idx + 1], (VFS_OPEN_MODES) request->mode)); msg.signal = SIGNAL_OK; // send_message(&msg, msg.sender); } } else if(node->getType() == NODE_MOUNT) { FSMount* mount = static_cast<FSMount*>(node); file->device = mount->getFilesystemDriver(); file->type = VFS_MOUNTPOINT; file->uid = mount->getUID(); file->guid = mount->getGUID(); std::string path; path = request->path; path = path.substr(strlen(mount->getPath())); if(path.empty()) path = "/"; strcpy(file->path, path.c_str()); msg.signal = SIGNAL_OK; } send_message(&msg, sender); } break; case VFS_SIGNAL_STAT: { struct stat* st = (struct stat*) &msg.message; pid_t sender = msg.sender; FSNode* node = rootfs.findNode(request->path); if (!node) { msg.signal = SIGNAL_FAIL; send_message(&msg, msg.sender); break; } st->st_dev = msg.receiver; st->st_mode = node->getType(); switch(node->getType()) { case NODE_DEVICE: st->st_mode = VFS_CHARACTER_DEVICE; break; case NODE_DIR: st->st_mode = VFS_DIRECTORY; break; case NODE_MOUNT: st->st_mode = VFS_MOUNTPOINT; break; } msg.signal = SIGNAL_OK; send_message(&msg, msg.sender); } break; default: { // debug_printf("[ VFS ] Unknown signal %d from %d\n", msg.signal, msg.sender); } } } for (;;); }
bool FSNode::operator<(const FSNode& node) const { if (isDirectory() != node.isDirectory()) return isDirectory(); return getDisplayName().compareToIgnoreCase(node.getDisplayName()) < 0; }