* 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:
parent
b0884f0cb8
commit
49a7b6198d
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user