Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
unix: don't alloc memory for readdir on empty dir
  • Loading branch information
bnoordhuis committed Oct 10, 2011
1 parent 04b356a commit 41e8574
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 8 deletions.
17 changes: 9 additions & 8 deletions src/unix/fs.c
Expand Up @@ -85,8 +85,7 @@ void uv_fs_req_cleanup(uv_fs_t* req) {

switch (req->fs_type) {
case UV_FS_READDIR:
assert((req->result == -1 && req->ptr == NULL)
|| (req->result >= 0 && req->ptr != NULL));
assert(req->result > 0 ? (req->ptr != NULL) : (req->ptr == NULL));
free(req->ptr);
req->ptr = NULL;
break;
Expand Down Expand Up @@ -116,9 +115,6 @@ static int uv__fs_after(eio_req* eio) {

switch (req->fs_type) {
case UV_FS_READDIR:
if (req->eio->result == -1)
break; /* opendir() or readdir() operation failed. */

/*
* XXX This is pretty bad.
* We alloc and copy the large null terminated string list from libeio.
Expand All @@ -128,16 +124,21 @@ static int uv__fs_after(eio_req* eio) {
*/
buflen = 0;
name = req->eio->ptr2;

for (i = 0; i < req->result; i++) {
namelen = strlen(name);
buflen += namelen + 1;
/* TODO check ENOMEM */
name += namelen;
assert(*name == '\0');
name++;
}
req->ptr = malloc(buflen);
memcpy(req->ptr, req->eio->ptr2, buflen);

if (buflen) {
if ((req->ptr = malloc(buflen)))
memcpy(req->ptr, req->eio->ptr2, buflen);
else
uv__set_sys_error(req->loop, ENOMEM);
}
break;

case UV_FS_STAT:
Expand Down
41 changes: 41 additions & 0 deletions test/test-fs.c
Expand Up @@ -354,6 +354,16 @@ static void readdir_cb(uv_fs_t* req) {
}


static void empty_readdir_cb(uv_fs_t* req) {
ASSERT(req == &readdir_req);
ASSERT(req->fs_type == UV_FS_READDIR);
ASSERT(req->result == 0);
ASSERT(req->ptr == NULL);
uv_fs_req_cleanup(req);
readdir_cb_count++;
}


static void stat_cb(uv_fs_t* req) {
ASSERT(req == &stat_req);
ASSERT(req->fs_type == UV_FS_STAT || req->fs_type == UV_FS_LSTAT);
Expand Down Expand Up @@ -1292,3 +1302,34 @@ TEST_IMPL(fs_stat_missing_path) {

return 0;
}


TEST_IMPL(fs_readdir_empty_dir) {
const char* path;
uv_fs_t req;
int r;

path = "./empty_dir/";
loop = uv_default_loop();

uv_fs_mkdir(loop, &req, path, 0777, NULL);
uv_fs_req_cleanup(&req);

r = uv_fs_readdir(loop, &req, path, 0, NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
ASSERT(req.ptr == NULL);
uv_fs_req_cleanup(&req);

r = uv_fs_readdir(loop, &readdir_req, path, 0, empty_readdir_cb);
ASSERT(r == 0);

ASSERT(readdir_cb_count == 0);
uv_run(loop);
ASSERT(readdir_cb_count == 1);

uv_fs_rmdir(loop, &req, path, NULL);
uv_fs_req_cleanup(&req);

return 0;
}
2 changes: 2 additions & 0 deletions test/test-list.h
Expand Up @@ -99,6 +99,7 @@ TEST_DECLARE (fs_stat_missing_path)
TEST_DECLARE (fs_event_watch_dir)
TEST_DECLARE (fs_event_watch_file)
TEST_DECLARE (fs_event_watch_file_current_dir)
TEST_DECLARE (fs_readdir_empty_dir)
TEST_DECLARE (threadpool_queue_work_simple)
#ifdef _WIN32
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
Expand Down Expand Up @@ -232,6 +233,7 @@ TASK_LIST_START
TEST_ENTRY (fs_event_watch_dir)
TEST_ENTRY (fs_event_watch_file)
TEST_ENTRY (fs_event_watch_file_current_dir)
TEST_ENTRY (fs_readdir_empty_dir)

TEST_ENTRY (threadpool_queue_work_simple)

Expand Down

0 comments on commit 41e8574

Please sign in to comment.