* cdda_read_dir() did not correctly report the number of entries put into
the dirent buffer. This fixes Rene's comment about "ls" entering an endless loop. * It also didn't access the buffer passed in correctly if it came from userland. * It now also fills in as many entries in the buffer as fit. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26861 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1672,11 +1672,10 @@ cdda_open_dir(fs_volume *_volume, fs_vnode *_node, void **_cookie)
|
|||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cdda_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
cdda_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||||
struct dirent *dirent, size_t bufferSize, uint32 *_num)
|
struct dirent *buffer, size_t bufferSize, uint32 *_num)
|
||||||
{
|
{
|
||||||
Volume *volume = (Volume *)_volume->private_volume;
|
Volume *volume = (Volume *)_volume->private_volume;
|
||||||
Inode *inode = (Inode *)_node->private_node;
|
Inode *inode = (Inode *)_node->private_node;
|
||||||
status_t status = 0;
|
|
||||||
|
|
||||||
TRACE(("cdda_read_dir: vnode %p, cookie %p, buffer = %p, bufferSize = %ld, num = %p\n", _node, _cookie, dirent, bufferSize,_num));
|
TRACE(("cdda_read_dir: vnode %p, cookie %p, buffer = %p, bufferSize = %ld, num = %p\n", _node, _cookie, dirent, bufferSize,_num));
|
||||||
|
|
||||||
@@ -1690,7 +1689,10 @@ cdda_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
|||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
Inode *nextChildNode = NULL;
|
Inode *nextChildNode = NULL;
|
||||||
int nextState = cookie->state;
|
int nextState = cookie->state;
|
||||||
|
uint32 max = *_num;
|
||||||
|
uint32 count = 0;
|
||||||
|
|
||||||
|
while (count < max && bufferSize > sizeof(dirent)) {
|
||||||
switch (cookie->state) {
|
switch (cookie->state) {
|
||||||
case ITERATION_STATE_DOT:
|
case ITERATION_STATE_DOT:
|
||||||
childNode = inode;
|
childNode = inode;
|
||||||
@@ -1713,25 +1715,36 @@ cdda_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!childNode) {
|
if (childNode == NULL) {
|
||||||
// we're at the end of the directory
|
// we're at the end of the directory
|
||||||
*_num = 0;
|
break;
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dirent->d_dev = volume->FSVolume()->id;
|
struct dirent entry;
|
||||||
dirent->d_ino = inode->ID();
|
entry.d_dev = volume->FSVolume()->id;
|
||||||
dirent->d_reclen = strlen(name) + sizeof(struct dirent);
|
entry.d_ino = childNode->ID();
|
||||||
|
entry.d_reclen = strlen(name) + sizeof(struct dirent);
|
||||||
|
|
||||||
if (dirent->d_reclen > bufferSize)
|
if (entry.d_reclen > bufferSize) {
|
||||||
|
if (count == 0)
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
|
|
||||||
status = user_strlcpy(dirent->d_name, name, bufferSize);
|
break;
|
||||||
if (status < B_OK)
|
}
|
||||||
return status;
|
|
||||||
|
if (user_memcpy(buffer, &entry, sizeof(struct dirent) - 1) != B_OK
|
||||||
|
|| user_strlcpy(buffer->d_name, name, bufferSize) < B_OK)
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
buffer = (struct dirent*)((uint8*)buffer + entry.d_reclen);
|
||||||
|
bufferSize -= entry.d_reclen;
|
||||||
|
count++;
|
||||||
|
|
||||||
cookie->current = nextChildNode;
|
cookie->current = nextChildNode;
|
||||||
cookie->state = nextState;
|
cookie->state = nextState;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_num = count;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user