unix fs_async_dir works
This commit is contained in:
parent
cf08c168ea
commit
0e81406bfb
@ -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
|
||||
|
||||
181
src/unix/fs.c
181
src/unix/fs.c
@ -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>
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user