diff --git a/Kernel/FileDescriptor.cpp b/Kernel/FileDescriptor.cpp index 5aea6d181f8..42e144cc1e5 100644 --- a/Kernel/FileDescriptor.cpp +++ b/Kernel/FileDescriptor.cpp @@ -278,8 +278,9 @@ ssize_t FileDescriptor::get_dir_entries(byte* buffer, ssize_t size) if (!metadata.is_directory()) return -ENOTDIR; - // FIXME: Compute the actual size needed. - auto temp_buffer = ByteBuffer::create_uninitialized(2048); + int size_to_allocate = max(PAGE_SIZE, metadata.size); + + auto temp_buffer = ByteBuffer::create_uninitialized(size_to_allocate); BufferStream stream(temp_buffer); VFS::the().traverse_directory_inode(*m_inode, [&stream] (auto& entry) { stream << (dword)entry.inode.index(); @@ -288,11 +289,12 @@ ssize_t FileDescriptor::get_dir_entries(byte* buffer, ssize_t size) stream << entry.name; return true; }); + stream.snip(); - if (size < stream.offset()) + if (size < temp_buffer.size()) return -1; - memcpy(buffer, temp_buffer.pointer(), stream.offset()); + memcpy(buffer, temp_buffer.pointer(), temp_buffer.size()); return stream.offset(); } diff --git a/LibC/dirent.cpp b/LibC/dirent.cpp index ef1ec33bc21..f9c8d33db1b 100644 --- a/LibC/dirent.cpp +++ b/LibC/dirent.cpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include extern "C" { @@ -54,9 +57,13 @@ dirent* readdir(DIR* dirp) return nullptr; if (!dirp->buffer) { - // FIXME: Figure out how much to actually allocate. - dirp->buffer = (char*)malloc(4096); - ssize_t nread = syscall(SC_get_dir_entries, dirp->fd, dirp->buffer, 4096); + struct stat st; + int rc = fstat(dirp->fd, &st); + if (rc < 0) + return nullptr; + size_t size_to_allocate = max(st.st_size, 4096); + dirp->buffer = (char*)malloc(size_to_allocate); + ssize_t nread = syscall(SC_get_dir_entries, dirp->fd, dirp->buffer, size_to_allocate); dirp->buffer_size = nread; dirp->nextptr = dirp->buffer; }