* fix_dirent() now correctly handles buffers from userland.

* dir_read() now takes into account that we may have read more than one dir
  entry, and calls fix_dirent() for each of them.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26859 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-08-07 14:23:44 +00:00
parent b0884f0cb8
commit 49a7b6198d

View File

@ -5144,10 +5144,25 @@ dir_read(struct io_context* ioContext, struct file_descriptor *descriptor,
}
static void
fix_dirent(struct vnode *parent, struct dirent *entry,
struct io_context* ioContext)
static status_t
fix_dirent(struct vnode *parent, struct dirent *userEntry,
struct io_context* ioContext, uint32* _length)
{
char buffer[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
struct dirent* entry;
if (IS_USER_ADDRESS(userEntry)) {
unsigned short length;
entry = (struct dirent*)buffer;
if (user_memcpy(&length, &userEntry->d_reclen, sizeof(length)) != B_OK
|| user_memcpy(entry, userEntry, length) != B_OK)
return B_BAD_ADDRESS;
} else
entry = userEntry;
*_length = entry->d_reclen;
// set d_pdev and d_pino
entry->d_pdev = parent->device;
entry->d_pino = parent->id;
@ -5181,7 +5196,7 @@ fix_dirent(struct vnode *parent, struct dirent *entry,
status_t status = get_vnode(entry->d_dev, entry->d_ino, &vnode, true,
false);
if (status != B_OK)
return;
return status;
mutex_lock(&sVnodeCoveredByMutex);
if (vnode->covered_by) {
@ -5192,6 +5207,12 @@ fix_dirent(struct vnode *parent, struct dirent *entry,
put_vnode(vnode);
}
// copy back from userland buffer if needed
if (entry != userEntry)
return user_memcpy(userEntry, entry, sizeof(struct dirent) - 1);
return B_OK;
}
@ -5208,9 +5229,16 @@ dir_read(struct io_context* ioContext, struct vnode *vnode, void *cookie,
return error;
// we need to adjust the read dirents
if (*_count > 0) {
// XXX: Currently reading only one dirent is supported. Make this a loop!
fix_dirent(vnode, buffer, ioContext);
uint32 count = *_count;
if (count > 0) {
for (uint32 i = 0; i < count; i++) {
uint32 length;
error = fix_dirent(vnode, buffer, ioContext, &length);
if (error != B_OK)
return error;
buffer = (struct dirent*)((uint8*)buffer + length);
}
}
return error;