mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +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:
parent
c3cc318028
commit
c4fce9b3f9
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -59,10 +59,11 @@ RetainPtr<FileDescriptor> 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;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/CircularQueue.h>
|
||||
#include <AK/Retainable.h>
|
||||
#include <AK/Badge.h>
|
||||
|
||||
class TTY;
|
||||
class MasterPTY;
|
||||
|
@ -68,6 +69,8 @@ public:
|
|||
|
||||
ByteBuffer& generator_cache() { return m_generator_cache; }
|
||||
|
||||
void set_original_inode(Badge<VFS>, RetainPtr<Inode>&& inode) { m_inode = move(inode); }
|
||||
|
||||
private:
|
||||
friend class VFS;
|
||||
explicit FileDescriptor(RetainPtr<Inode>&&);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -146,13 +146,15 @@ RetainPtr<FileDescriptor> 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<VFS>(), move(inode));
|
||||
return descriptor;
|
||||
}
|
||||
return FileDescriptor::create(move(inode));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <AK/AKString.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(" %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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue