1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:58:11 +00:00

Make stat() work on device files again.

FileDescriptor will now keep a pointer to the original inode even after
opening it resolves to a character device.

Fixed up /bin/ls to display major and minor device numbers instead of size
for device files.
This commit is contained in:
Andreas Kling 2019-01-31 05:05:57 +01:00
parent c3cc318028
commit c4fce9b3f9
8 changed files with 25 additions and 10 deletions

View file

@ -360,7 +360,7 @@ InodeMetadata Ext2FSInode::metadata() const
if (isBlockDevice(m_raw_inode.i_mode) || isCharacterDevice(m_raw_inode.i_mode)) { if (isBlockDevice(m_raw_inode.i_mode) || isCharacterDevice(m_raw_inode.i_mode)) {
unsigned dev = m_raw_inode.i_block[0]; unsigned dev = m_raw_inode.i_block[0];
metadata.majorDevice = (dev & 0xfff00) >> 8; metadata.majorDevice = (dev & 0xfff00) >> 8;
metadata.minorDevice= (dev & 0xff) | ((dev >> 12) & 0xfff00); metadata.minorDevice = (dev & 0xff) | ((dev >> 12) & 0xfff00);
} }
return metadata; return metadata;
} }

View file

@ -59,10 +59,11 @@ RetainPtr<FileDescriptor> FileDescriptor::clone()
? FileDescriptor::create_pipe_reader(*m_fifo) ? FileDescriptor::create_pipe_reader(*m_fifo)
: FileDescriptor::create_pipe_writer(*m_fifo); : FileDescriptor::create_pipe_writer(*m_fifo);
} else { } else {
if (m_inode) if (m_device) {
descriptor = FileDescriptor::create(m_inode.copyRef());
else {
descriptor = FileDescriptor::create(m_device.copyRef()); descriptor = FileDescriptor::create(m_device.copyRef());
descriptor->m_inode = m_inode.copyRef();
} else {
descriptor = FileDescriptor::create(m_inode.copyRef());
} }
} }
if (!descriptor) if (!descriptor)
@ -90,7 +91,7 @@ int FileDescriptor::fstat(stat* buffer)
if (!metadata.isValid()) if (!metadata.isValid())
return -EIO; return -EIO;
buffer->st_dev = 0; // FIXME buffer->st_dev = encodedDevice(metadata.majorDevice, metadata.minorDevice);
buffer->st_ino = metadata.inode.index(); buffer->st_ino = metadata.inode.index();
buffer->st_mode = metadata.mode; buffer->st_mode = metadata.mode;
buffer->st_nlink = metadata.linkCount; buffer->st_nlink = metadata.linkCount;

View file

@ -6,6 +6,7 @@
#include <AK/ByteBuffer.h> #include <AK/ByteBuffer.h>
#include <AK/CircularQueue.h> #include <AK/CircularQueue.h>
#include <AK/Retainable.h> #include <AK/Retainable.h>
#include <AK/Badge.h>
class TTY; class TTY;
class MasterPTY; class MasterPTY;
@ -68,6 +69,8 @@ public:
ByteBuffer& generator_cache() { return m_generator_cache; } ByteBuffer& generator_cache() { return m_generator_cache; }
void set_original_inode(Badge<VFS>, RetainPtr<Inode>&& inode) { m_inode = move(inode); }
private: private:
friend class VFS; friend class VFS;
explicit FileDescriptor(RetainPtr<Inode>&&); explicit FileDescriptor(RetainPtr<Inode>&&);

View file

@ -1215,7 +1215,7 @@ int Process::sys$lstat(const char* path, stat* statbuf)
if (!validate_write_typed(statbuf)) if (!validate_write_typed(statbuf))
return -EFAULT; return -EFAULT;
int error; 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) if (!descriptor)
return error; return error;
descriptor->fstat(statbuf); descriptor->fstat(statbuf);
@ -1227,7 +1227,7 @@ int Process::sys$stat(const char* path, stat* statbuf)
if (!validate_write_typed(statbuf)) if (!validate_write_typed(statbuf))
return -EFAULT; return -EFAULT;
int error; 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) if (!descriptor)
return error; return error;
descriptor->fstat(statbuf); descriptor->fstat(statbuf);

View file

@ -146,13 +146,15 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options,
return nullptr; return nullptr;
} }
auto metadata = inode->metadata(); 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)); auto it = m_character_devices.find(encodedDevice(metadata.majorDevice, metadata.minorDevice));
if (it == m_character_devices.end()) { if (it == m_character_devices.end()) {
kprintf("VFS::open: no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice); kprintf("VFS::open: no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice);
return nullptr; return nullptr;
} }
return (*it).value->open(error, options); auto descriptor = (*it).value->open(error, options);
descriptor->set_original_inode(Badge<VFS>(), move(inode));
return descriptor;
} }
return FileDescriptor::create(move(inode)); return FileDescriptor::create(move(inode));
} }

View file

@ -24,6 +24,7 @@
#define O_NOFOLLOW 00400000 #define O_NOFOLLOW 00400000
#define O_CLOEXEC 02000000 #define O_CLOEXEC 02000000
#define O_NOFOLLOW_NOERROR 0x4000000 #define O_NOFOLLOW_NOERROR 0x4000000
#define O_DONT_OPEN_DEVICE 0x8000000
class CharacterDevice; class CharacterDevice;
class FileDescriptor; class FileDescriptor;

View file

@ -9,4 +9,8 @@ mode_t umask(mode_t);
int chmod(const char* pathname, mode_t); int chmod(const char* pathname, mode_t);
int mkdir(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 __END_DECLS

View file

@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include <getopt.h> #include <getopt.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h>
#include <AK/AKString.h> #include <AK/AKString.h>
#include <AK/Vector.h> #include <AK/Vector.h>
@ -150,7 +151,10 @@ int do_dir(const char* path)
printf(" %4u %4u", st.st_uid, st.st_gid); 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); printf(" %10u ", st.st_mtime);