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

Commit

Permalink
unix fs_async_dir works
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Aug 30, 2011
1 parent cf08c16 commit 0e81406
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 9 deletions.
1 change: 1 addition & 0 deletions include/uv-unix.h
Expand Up @@ -159,6 +159,7 @@ typedef int uv_file;
ev_child child_watcher;

#define UV_FS_PRIVATE_FIELDS \
struct stat statbuf; \
eio_req* eio;

#define UV_WORK_PRIVATE_FIELDS
Expand Down
181 changes: 173 additions & 8 deletions src/unix/fs.c
Expand Up @@ -24,6 +24,9 @@
#include "eio.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
Expand All @@ -46,16 +49,59 @@ static void uv_fs_req_init(uv_fs_t* req, uv_fs_type fs_type, uv_fs_cb cb) {


void uv_fs_req_cleanup(uv_fs_t* req) {
switch (req->fs_type) {
case UV_FS_READDIR:
assert(req->ptr);
free(req->ptr);
req->ptr = NULL;
break;

case UV_FS_STAT:
req->ptr = NULL;
break;

default:
break;
}
}


static int uv__fs_after(eio_req* eio) {
char* name;
int namelen;
int buflen = 0;
uv_fs_t* req = eio->data;
int i;

assert(req->cb);

req->result = req->eio->result;
req->errorno = req->eio->errorno;

if (req->fs_type == UV_FS_READDIR) {
/*
* XXX This is pretty bad.
* We alloc and copy the large null termiated string list from libeio.
* This is done because libeio is going to free eio->ptr2 after this
* callback. We must keep it until uv_fs_req_cleanup. If we get rid of
* libeio this can be avoided.
*/
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);
} else if (req->fs_type == UV_FS_STAT) {
req->ptr = req->eio->ptr2;
}

uv_unref();
req->eio = NULL; /* Freed by libeio */

Expand Down Expand Up @@ -202,26 +248,145 @@ int uv_fs_write(uv_fs_t* req, uv_file file, void* buf, size_t length,


int uv_fs_mkdir(uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
uv_fs_req_init(req, UV_FS_MKDIR, cb);

if (cb) {
/* async */
uv_ref();
req->eio = eio_mkdir(path, mode, EIO_PRI_DEFAULT, uv__fs_after, req);
if (!req->eio) {
uv_err_new(NULL, ENOMEM);
return -1;
}

} else {
/* sync */
req->result = mkdir(path, mode);

if (req->result < 0) {
uv_err_new(NULL, errno);
return -1;
}
}

return 0;
}


int uv_fs_rmdir(uv_fs_t* req, const char* path, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
uv_fs_req_init(req, UV_FS_RMDIR, cb);

if (cb) {
/* async */
uv_ref();
req->eio = eio_rmdir(path, EIO_PRI_DEFAULT, uv__fs_after, req);
if (!req->eio) {
uv_err_new(NULL, ENOMEM);
return -1;
}

} else {
/* sync */
req->result = rmdir(path);

if (req->result < 0) {
uv_err_new(NULL, errno);
return -1;
}
}

return 0;
}


int uv_fs_readdir(uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
int r;
struct dirent* entry;
size_t size = 0;

uv_fs_req_init(req, UV_FS_READDIR, cb);

if (cb) {
/* async */
uv_ref();
req->eio = eio_readdir(path, flags, EIO_PRI_DEFAULT, uv__fs_after, req);
if (!req->eio) {
uv_err_new(NULL, ENOMEM);
return -1;
}

} else {
/* sync */
DIR* dir = opendir(path);
if (!dir) {
uv_err_new(NULL, errno);
return -1;
}

while ((entry = readdir(dir))) {
req->ptr = realloc(req->ptr, size + entry->d_namlen + 1);
/* TODO check ENOMEM */
/* TODO skip . and .. */
memcpy((char*)req->ptr + size, entry->d_name, entry->d_namlen);
size += entry->d_namlen;
((char*)req->ptr)[size] = '\0';
size++;
}

r = closedir(dir);
if (r) {
uv_err_new(NULL, errno);
return -1;
}
}

return 0;
}


int uv_fs_stat(uv_fs_t* req, const char* path, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
char* pathdup = path;
int pathlen;

uv_fs_req_init(req, UV_FS_STAT, cb);

/* TODO do this without duplicating the string. */
/* TODO security */
pathdup = strdup(path);
pathlen = strlen(path);

if (pathlen > 0 && path[pathlen - 1] == '\\') {
/* TODO do not modify input string */
pathdup[pathlen - 1] = '\0';
}

if (cb) {
/* async */
uv_ref();
req->eio = eio_stat(pathdup, EIO_PRI_DEFAULT, uv__fs_after, req);

free(pathdup);

if (!req->eio) {
uv_err_new(NULL, ENOMEM);
return -1;
}

} else {
/* sync */
req->result = stat(pathdup, &req->statbuf);

free(pathdup);

if (req->result < 0) {
uv_err_new(NULL, errno);
return -1;
}

req->ptr = &req->statbuf;
}

return 0;
}


Expand Down
2 changes: 1 addition & 1 deletion test/test-fs.c
Expand Up @@ -398,7 +398,7 @@ TEST_IMPL(fs_async_dir) {

uv_init();

r = uv_fs_mkdir(&mkdir_req, "test_dir", 0, mkdir_cb);
r = uv_fs_mkdir(&mkdir_req, "test_dir", 0755, mkdir_cb);
ASSERT(r == 0);

uv_run();
Expand Down

0 comments on commit 0e81406

Please sign in to comment.