diff --git a/AK/FileSystemPath.cpp b/AK/FileSystemPath.cpp index fcba78420ef..ba907e4c798 100644 --- a/AK/FileSystemPath.cpp +++ b/AK/FileSystemPath.cpp @@ -30,32 +30,17 @@ bool FileSystemPath::canonicalize(bool resolveSymbolicLinks) canonicalParts.append(part); } if (canonicalParts.isEmpty()) { - m_string = m_basename = m_dirname = "/"; + m_string = m_basename = "/"; return true; } m_basename = canonicalParts.last(); - - if (canonicalParts.size() == 1) { - m_dirname = "/"; - } else { - StringBuilder builder; - for (size_t i = 0; i < canonicalParts.size() - 1; ++i) { - auto& cpart = canonicalParts[i]; - builder.append('/'); - builder.append(cpart); - } - m_dirname = builder.build(); - } - - { - StringBuilder builder; - for (auto& cpart : canonicalParts) { - builder.append('/'); - builder.append(move(cpart)); - } - m_string = builder.build(); + StringBuilder builder; + for (auto& cpart : canonicalParts) { + builder.append('/'); + builder.append(move(cpart)); } + m_string = builder.build(); return true; } diff --git a/AK/FileSystemPath.h b/AK/FileSystemPath.h index f53ec22d26d..7a3623d0cc7 100644 --- a/AK/FileSystemPath.h +++ b/AK/FileSystemPath.h @@ -13,13 +13,11 @@ public: String string() const { return m_string; } String basename() const { return m_basename; } - String dirname() const { return m_dirname; } private: bool canonicalize(bool resolveSymbolicLinks = false); String m_string; - String m_dirname; String m_basename; bool m_isValid { false }; }; diff --git a/VirtualFileSystem/Ext2FileSystem.cpp b/VirtualFileSystem/Ext2FileSystem.cpp index 2a21a423c11..7393bf2f29c 100644 --- a/VirtualFileSystem/Ext2FileSystem.cpp +++ b/VirtualFileSystem/Ext2FileSystem.cpp @@ -1011,7 +1011,7 @@ InodeIdentifier Ext2FS::create_inode(InodeIdentifier parentInode, const String& ASSERT(parentInode.fsid() == id()); ASSERT(isDirectoryInode(parentInode.index())); - dbgprintf("Ext2FS: Adding inode '%s' (mode %o) to parent directory %u:\n", name.characters(), mode, parentInode.index()); + dbgprintf("Ext2FS: Adding inode '%s' (mode %u) to parent directory %u:\n", name.characters(), mode, parentInode.index()); // NOTE: This doesn't commit the inode allocation just yet! auto inode = allocateInode(0, 0); diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index 34504dfa21e..6a51e49d680 100644 --- a/VirtualFileSystem/VirtualFileSystem.cpp +++ b/VirtualFileSystem/VirtualFileSystem.cpp @@ -13,10 +13,6 @@ static VFS* s_the; -#ifndef SERENITY -typedef int InterruptDisabler; -#endif - VFS& VFS::the() { ASSERT(s_the); @@ -130,11 +126,16 @@ auto VFS::get_or_create_node(CharacterDevice& device) -> RetainPtr return makeNode(device); } +InodeIdentifier VFS::root_inode_id() const +{ + return m_root_vnode->inode; +} + bool VFS::mount(RetainPtr&& fileSystem, const String& path) { ASSERT(fileSystem); int error; - auto inode = resolve_path(path, error); + auto inode = resolve_path(path, root_inode_id(), error); if (!inode.isValid()) { kprintf("VFS: mount can't resolve mount point '%s'\n", path.characters()); return false; @@ -209,18 +210,6 @@ void VFS::freeNode(Vnode* node) m_vnode_freelist.append(move(node)); } -#ifndef SERENITY -bool VFS::isDirectory(const String& path, InodeIdentifier base) -{ - int error; - auto inode = resolve_path(path, error, base); - if (!inode.isValid()) - return false; - - return inode.metadata().isDirectory(); -} -#endif - auto VFS::find_mount_for_host(InodeIdentifier inode) -> Mount* { for (auto& mount : m_mounts) { @@ -263,137 +252,10 @@ void VFS::traverse_directory_inode(CoreInode& dir_inode, Function %s %02u:%08u\n", path.characters(), directoryInode.fileSystem()->class_name(), directoryInode.fsid(), directoryInode.index()); - enumerateDirectoryInode(directoryInode, [&] (const FileSystem::DirectoryEntry& entry) { - const char* nameColorBegin = ""; - const char* nameColorEnd = ""; - auto metadata = entry.inode.metadata(); - ASSERT(metadata.isValid()); - if (metadata.isDirectory()) { - nameColorBegin = "\033[34;1m"; - nameColorEnd = "\033[0m"; - } else if (metadata.isSymbolicLink()) { - nameColorBegin = "\033[36;1m"; - nameColorEnd = "\033[0m"; - } - if (metadata.isSticky()) { - nameColorBegin = "\033[42;30m"; - nameColorEnd = "\033[0m"; - } - if (metadata.isCharacterDevice() || metadata.isBlockDevice()) { - nameColorBegin = "\033[33;1m"; - nameColorEnd = "\033[0m"; - } - kprintf("%02u:%08u ", - metadata.inode.fsid(), - metadata.inode.index()); - - if (metadata.isDirectory()) - kprintf("d"); - else if (metadata.isSymbolicLink()) - kprintf("l"); - else if (metadata.isBlockDevice()) - kprintf("b"); - else if (metadata.isCharacterDevice()) - kprintf("c"); - else if (metadata.isSocket()) - kprintf("s"); - else if (metadata.isFIFO()) - kprintf("f"); - else if (metadata.isRegularFile()) - kprintf("-"); - else - kprintf("?"); - - kprintf("%c%c%c%c%c%c%c%c", - metadata.mode & 00400 ? 'r' : '-', - metadata.mode & 00200 ? 'w' : '-', - metadata.mode & 00100 ? 'x' : '-', - metadata.mode & 00040 ? 'r' : '-', - metadata.mode & 00020 ? 'w' : '-', - metadata.mode & 00010 ? 'x' : '-', - metadata.mode & 00004 ? 'r' : '-', - metadata.mode & 00002 ? 'w' : '-' - ); - - if (metadata.isSticky()) - kprintf("t"); - else - kprintf("%c", metadata.mode & 00001 ? 'x' : '-'); - - if (metadata.isCharacterDevice() || metadata.isBlockDevice()) { - char buf[16]; - ksprintf(buf, "%u, %u", metadata.majorDevice, metadata.minorDevice); - kprintf("%12s ", buf); - } else { - kprintf("%12lld ", metadata.size); - } - - kprintf("\033[30;1m"); - time_t mtime = metadata.mtime; - auto tm = *klocaltime(&mtime); - kprintf("%04u-%02u-%02u %02u:%02u:%02u ", - tm.tm_year + 1900, - tm.tm_mon + 1, - tm.tm_mday, - tm.tm_hour, - tm.tm_min, - tm.tm_sec); - kprintf("\033[0m"); - - kprintf("%s%s%s", - nameColorBegin, - entry.name, - nameColorEnd); - - if (metadata.isDirectory()) { - kprintf("/"); - } else if (metadata.isSymbolicLink()) { - auto symlinkContents = directoryInode.fileSystem()->readEntireInode(metadata.inode); - kprintf(" -> %s", String((const char*)symlinkContents.pointer(), symlinkContents.size()).characters()); - } - kprintf("\n"); - return true; - }); -} - -void VFS::listDirectoryRecursively(const String& path, InodeIdentifier base) -{ - int error; - auto directory = resolve_path(path, error, base); - if (!directory.isValid()) - return; - - kprintf("%s\n", path.characters()); - - enumerateDirectoryInode(directory, [&] (const FileSystem::DirectoryEntry& entry) { - auto metadata = entry.inode.metadata(); - if (metadata.isDirectory()) { - if (entry.name != "." && entry.name != "..") { - char buf[4096]; - ksprintf(buf, "%s/%s", path.characters(), entry.name); - listDirectoryRecursively(buf, base); - } - } else { - kprintf("%s/%s\n", path.characters(), entry.name); - } - return true; - }); -} -#endif - bool VFS::touch(const String& path) { int error; - auto inode = resolve_path(path, error); + auto inode = resolve_path(path, root_inode_id(), error); if (!inode.isValid()) return false; return inode.fileSystem()->set_mtime(inode, ktime(nullptr)); @@ -411,7 +273,7 @@ RetainPtr VFS::open(CharacterDevice& device, int options) RetainPtr VFS::open(const String& path, int& error, int options, InodeIdentifier base) { - auto inode = resolve_path(path, error, base, options); + auto inode = resolve_path(path, base, error, options); if (!inode.isValid()) return nullptr; auto vnode = get_or_create_node(inode); @@ -438,10 +300,24 @@ bool VFS::mkdir(const String& path, mode_t mode, InodeIdentifier base, int& erro error = -EINVAL; return false; } - dbgprintf("VFS::mkdir: '%s' in '%s'\n", p.basename().characters(), p.dirname().characters()); - auto parent_dir = resolve_path(p.dirname(), error, m_root_vnode->inode); - if (!parent_dir.isValid()) + + InodeIdentifier parent_dir; + auto existing_dir = resolve_path(path, base, error, 0, &parent_dir); + if (existing_dir.isValid()) { + kprintf("fug\n"); + error = -EEXIST; return false; + } + if (!parent_dir.isValid()) { + kprintf("fug2\n"); + error = -ENOENT; + return false; + } + if (error != -ENOENT) { + kprintf("fug3\n"); + return false; + } + dbgprintf("VFS::mkdir: '%s' in %u:%u\n", p.basename().characters(), parent_dir.fsid(), parent_dir.index()); auto new_dir = base.fileSystem()->create_directory(parent_dir, p.basename(), mode, error); if (new_dir.isValid()) { error = 0; @@ -459,7 +335,7 @@ InodeIdentifier VFS::resolveSymbolicLink(InodeIdentifier base, InodeIdentifier s #ifdef VFS_DEBUG kprintf("linkee (%s)(%u) from %u:%u\n", linkee.characters(), linkee.length(), base.fsid(), base.index()); #endif - return resolve_path(linkee, error, base); + return resolve_path(linkee, base, error); } RetainPtr VFS::get_inode(InodeIdentifier inode_id) @@ -482,7 +358,7 @@ String VFS::absolute_path(CoreInode& core_inode) InodeIdentifier parent_id; if (inode->is_directory()) { - parent_id = resolve_path("..", error, inode->identifier()); + parent_id = resolve_path("..", inode->identifier(), error); } else { parent_id = inode->fs().find_parent_of_inode(inode->identifier()); } @@ -505,10 +381,12 @@ String VFS::absolute_path(CoreInode& core_inode) return builder.build(); } -InodeIdentifier VFS::resolve_path(const String& path, int& error, InodeIdentifier base, int options) +InodeIdentifier VFS::resolve_path(const String& path, InodeIdentifier base, int& error, int options, InodeIdentifier* deepest_dir) { - if (path.isEmpty()) + if (path.isEmpty()) { + error = -EINVAL; return { }; + } auto parts = path.split('/'); InodeIdentifier crumb_id; @@ -518,6 +396,9 @@ InodeIdentifier VFS::resolve_path(const String& path, int& error, InodeIdentifie else crumb_id = base.isValid() ? base : m_root_vnode->inode; + if (deepest_dir) + *deepest_dir = crumb_id; + for (unsigned i = 0; i < parts.size(); ++i) { bool inode_was_root_at_head_of_loop = crumb_id.isRootInode(); auto& part = parts[i]; @@ -535,7 +416,7 @@ InodeIdentifier VFS::resolve_path(const String& path, int& error, InodeIdentifie #ifdef VFS_DEBUG kprintf("parent of <%s> not directory, it's inode %u:%u / %u:%u, mode: %u, size: %u\n", part.characters(), inode.fsid(), inode.index(), metadata.inode.fsid(), metadata.inode.index(), metadata.mode, metadata.size); #endif - error = -EIO; + error = -ENOTDIR; return { }; } auto parent = crumb_id; @@ -566,6 +447,10 @@ InodeIdentifier VFS::resolve_path(const String& path, int& error, InodeIdentifie crumb_id = dir_inode->lookup(".."); } metadata = crumb_id.metadata(); + if (metadata.isDirectory()) { + if (deepest_dir) + *deepest_dir = crumb_id; + } if (metadata.isSymbolicLink()) { if (i == parts.size() - 1) { if (options & O_NOFOLLOW) { diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index a85f09c2c78..e5960e2af92 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -98,12 +98,6 @@ public: VFS(); ~VFS(); -#ifndef SERENITY - bool isDirectory(const String& path, InodeIdentifier base = InodeIdentifier()); - void listDirectory(const String& path, InodeIdentifier base); - void listDirectoryRecursively(const String& path, InodeIdentifier base); -#endif - unsigned max_vnode_count() const { return m_max_vnode_count; } unsigned allocated_vnode_count() const { return m_max_vnode_count - m_vnode_freelist.size(); } @@ -127,6 +121,8 @@ public: String absolute_path(CoreInode&); + InodeIdentifier root_inode_id() const; + private: friend class FileDescriptor; friend class Vnode; @@ -136,7 +132,7 @@ private: bool is_vfs_root(InodeIdentifier) const; void traverse_directory_inode(CoreInode&, Function); - InodeIdentifier resolve_path(const String& path, int& error, InodeIdentifier base = InodeIdentifier(), int options = 0); + InodeIdentifier resolve_path(const String& path, InodeIdentifier base, int& error, int options = 0, InodeIdentifier* deepest_dir = nullptr); InodeIdentifier resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error); RetainPtr allocateNode();