diff --git a/Kernel/Ext2FileSystem.cpp b/Kernel/Ext2FileSystem.cpp index a06f2a51093..a5f3761dc0c 100644 --- a/Kernel/Ext2FileSystem.cpp +++ b/Kernel/Ext2FileSystem.cpp @@ -360,7 +360,7 @@ InodeMetadata Ext2FSInode::metadata() const if (isBlockDevice(m_raw_inode.i_mode) || isCharacterDevice(m_raw_inode.i_mode)) { unsigned dev = m_raw_inode.i_block[0]; metadata.majorDevice = (dev & 0xfff00) >> 8; - metadata.minorDevice= (dev & 0xff) | ((dev >> 12) & 0xfff00); + metadata.minorDevice = (dev & 0xff) | ((dev >> 12) & 0xfff00); } return metadata; } diff --git a/Kernel/FileDescriptor.cpp b/Kernel/FileDescriptor.cpp index 17f6834ce20..b8a0619cf84 100644 --- a/Kernel/FileDescriptor.cpp +++ b/Kernel/FileDescriptor.cpp @@ -59,10 +59,11 @@ RetainPtr FileDescriptor::clone() ? FileDescriptor::create_pipe_reader(*m_fifo) : FileDescriptor::create_pipe_writer(*m_fifo); } else { - if (m_inode) - descriptor = FileDescriptor::create(m_inode.copyRef()); - else { + if (m_device) { descriptor = FileDescriptor::create(m_device.copyRef()); + descriptor->m_inode = m_inode.copyRef(); + } else { + descriptor = FileDescriptor::create(m_inode.copyRef()); } } if (!descriptor) @@ -90,7 +91,7 @@ int FileDescriptor::fstat(stat* buffer) if (!metadata.isValid()) return -EIO; - buffer->st_dev = 0; // FIXME + buffer->st_dev = encodedDevice(metadata.majorDevice, metadata.minorDevice); buffer->st_ino = metadata.inode.index(); buffer->st_mode = metadata.mode; buffer->st_nlink = metadata.linkCount; diff --git a/Kernel/FileDescriptor.h b/Kernel/FileDescriptor.h index 38195d4c1ea..fb08b097905 100644 --- a/Kernel/FileDescriptor.h +++ b/Kernel/FileDescriptor.h @@ -6,6 +6,7 @@ #include #include #include +#include class TTY; class MasterPTY; @@ -68,6 +69,8 @@ public: ByteBuffer& generator_cache() { return m_generator_cache; } + void set_original_inode(Badge, RetainPtr&& inode) { m_inode = move(inode); } + private: friend class VFS; explicit FileDescriptor(RetainPtr&&); diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 62963947bfa..3160cb4d66d 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1215,7 +1215,7 @@ int Process::sys$lstat(const char* path, stat* statbuf) if (!validate_write_typed(statbuf)) return -EFAULT; int error; - auto descriptor = VFS::the().open(move(path), error, O_NOFOLLOW_NOERROR, 0, cwd_inode()->identifier()); + auto descriptor = VFS::the().open(move(path), error, O_NOFOLLOW_NOERROR | O_DONT_OPEN_DEVICE, 0, cwd_inode()->identifier()); if (!descriptor) return error; descriptor->fstat(statbuf); @@ -1227,7 +1227,7 @@ int Process::sys$stat(const char* path, stat* statbuf) if (!validate_write_typed(statbuf)) return -EFAULT; int error; - auto descriptor = VFS::the().open(move(path), error, 0, 0, cwd_inode()->identifier()); + auto descriptor = VFS::the().open(move(path), error, O_DONT_OPEN_DEVICE, 0, cwd_inode()->identifier()); if (!descriptor) return error; descriptor->fstat(statbuf); diff --git a/Kernel/VirtualFileSystem.cpp b/Kernel/VirtualFileSystem.cpp index 261fdc9493e..c2200f0792e 100644 --- a/Kernel/VirtualFileSystem.cpp +++ b/Kernel/VirtualFileSystem.cpp @@ -146,13 +146,15 @@ RetainPtr VFS::open(const String& path, int& error, int options, return nullptr; } auto metadata = inode->metadata(); - if (metadata.isCharacterDevice()) { + if (!(options & O_DONT_OPEN_DEVICE) && metadata.isCharacterDevice()) { auto it = m_character_devices.find(encodedDevice(metadata.majorDevice, metadata.minorDevice)); if (it == m_character_devices.end()) { kprintf("VFS::open: no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice); return nullptr; } - return (*it).value->open(error, options); + auto descriptor = (*it).value->open(error, options); + descriptor->set_original_inode(Badge(), move(inode)); + return descriptor; } return FileDescriptor::create(move(inode)); } diff --git a/Kernel/VirtualFileSystem.h b/Kernel/VirtualFileSystem.h index 563a2e89e9f..3bd677943f1 100644 --- a/Kernel/VirtualFileSystem.h +++ b/Kernel/VirtualFileSystem.h @@ -24,6 +24,7 @@ #define O_NOFOLLOW 00400000 #define O_CLOEXEC 02000000 #define O_NOFOLLOW_NOERROR 0x4000000 +#define O_DONT_OPEN_DEVICE 0x8000000 class CharacterDevice; class FileDescriptor; diff --git a/LibC/sys/stat.h b/LibC/sys/stat.h index e5fc40e5e5d..b1f6d860a73 100644 --- a/LibC/sys/stat.h +++ b/LibC/sys/stat.h @@ -9,4 +9,8 @@ mode_t umask(mode_t); int chmod(const char* pathname, mode_t); int mkdir(const char* pathname, mode_t); +inline dev_t makedev(unsigned int major, unsigned int minor) { return (minor & 0xffu) | (major << 8u) | ((minor & ~0xffu) << 12u); } +inline unsigned int major(dev_t dev) { return (dev & 0xfff00u) >> 8u; } +inline unsigned int minor(dev_t dev) { return (dev & 0xffu) | ((dev >> 12u) & 0xfff00u); } + __END_DECLS diff --git a/Userland/ls.cpp b/Userland/ls.cpp index 622dc928cca..da69b1e2326 100644 --- a/Userland/ls.cpp +++ b/Userland/ls.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -150,7 +151,10 @@ int do_dir(const char* path) printf(" %4u %4u", st.st_uid, st.st_gid); - printf(" %10u ", st.st_size); + if (S_ISCHR(st.st_mode)) + printf(" %4u,%4u ", major(st.st_dev), minor(st.st_dev)); + else + printf(" %10u ", st.st_size); printf(" %10u ", st.st_mtime);