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

Commit

Permalink
windows: implement missing fs functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor Zinkovsky committed Sep 3, 2011
1 parent 30ca028 commit cf5ed86
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 25 deletions.
149 changes: 131 additions & 18 deletions src/win/fs.c
Expand Up @@ -323,6 +323,50 @@ void fs__chmod(uv_fs_t* req, const char* path, int mode) {
}


void fs__fchmod(uv_fs_t* req, uv_file file, int mode) {
int result;
HANDLE handle;
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_BASIC_INFORMATION file_info;

handle = (HANDLE)_get_osfhandle(file);

nt_status = pNtQueryInformationFile(handle,
&io_status,
&file_info,
sizeof file_info,
FileBasicInformation);

if (nt_status != STATUS_SUCCESS) {
result = -1;
goto done;
}

if (mode & _S_IWRITE) {
file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
} else {
file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
}

nt_status = pNtSetInformationFile(handle,
&io_status,
&file_info,
sizeof file_info,
FileBasicInformation);

if (nt_status != STATUS_SUCCESS) {
result = -1;
goto done;
}

result = 0;

done:
SET_REQ_RESULT(req, result);
}


void fs__utime(uv_fs_t* req, const char* path, double atime, double mtime) {
int result;
struct _utimbuf b = {(time_t)atime, (time_t)mtime};
Expand All @@ -339,6 +383,11 @@ void fs__futime(uv_fs_t* req, uv_file file, double atime, double mtime) {
}


void fs__nop(uv_fs_t* req) {
req->result = 0;
}


static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
uv_fs_t* req = (uv_fs_t*) parameter;
uv_loop_t* loop = req->loop;
Expand Down Expand Up @@ -380,6 +429,7 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
fs__readdir(req, (const char*)req->arg0, (int)req->arg1);
break;
case UV_FS_STAT:
case UV_FS_LSTAT:
fs__stat(req, (const char*)req->arg0);
break;
case UV_FS_FSTAT:
Expand All @@ -405,12 +455,19 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
case UV_FS_CHMOD:
fs__chmod(req, (const char*)req->arg0, (int)req->arg1);
break;
case UV_FS_FCHMOD:
fs__fchmod(req, (uv_file)req->arg0, (int)req->arg1);
break;
case UV_FS_UTIME:
fs__utime(req, (const char*)req->arg0, req->arg4, req->arg5);
break;
case UV_FS_FUTIME:
fs__futime(req, (uv_file)req->arg0, req->arg4, req->arg5);
break;
case UV_FS_CHOWN:
case UV_FS_FCHOWN:
fs__nop(req);
break;
default:
assert(!"bad uv_fs_type");
}
Expand Down Expand Up @@ -544,13 +601,6 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
}


int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
}


// uv_fs_readlink, uv_fs_fchmod, uv_fs_chown, uv_fs_fchown
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb) {
assert(0 && "implement me");
Expand All @@ -572,24 +622,34 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
}


int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode,
uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
}


int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid,
int gid, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_CHOWN, cb);
WRAP_REQ_ARGS3(req, path, uid, gid);
STRDUP_ARG(req, 0);
QUEUE_FS_TP_JOB(loop, req);
} else {
uv_fs_req_init_sync(loop, req, UV_FS_CHOWN);
fs__nop(req);
}

return 0;
}


int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid,
int gid, uv_fs_cb cb) {
assert(0 && "implement me");
return -1;
if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_FCHOWN, cb);
WRAP_REQ_ARGS3(req, file, uid, gid);
QUEUE_FS_TP_JOB(loop, req);
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FCHOWN);
fs__nop(req);
}

return 0;
}


Expand Down Expand Up @@ -630,6 +690,44 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
}


/* TODO: add support for links. */
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
int len = strlen(path);
char* path2 = NULL;
int has_backslash = (path[len - 1] == '\\' || path[len - 1] == '/');

if (path[len - 1] == '\\' || path[len - 1] == '/') {
path2 = strdup(path);
if (!path2) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}

path2[len - 1] = '\0';
}

if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_LSTAT, cb);
if (path2) {
WRAP_REQ_ARGS1(req, path2);
req->flags |= UV_FS_FREE_ARG0;
} else {
WRAP_REQ_ARGS1(req, path);
STRDUP_ARG(req, 0);
}

QUEUE_FS_TP_JOB(loop, req);
} else {
uv_fs_req_init_sync(loop, req, UV_FS_LSTAT);
fs__stat(req, path2 ? path2 : path);
if (path2) {
free(path2);
}
}

return 0;
}


int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_FSTAT, cb);
Expand Down Expand Up @@ -735,6 +833,21 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
}


int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode,
uv_fs_cb cb) {
if (cb) {
uv_fs_req_init_async(loop, req, UV_FS_FCHMOD, cb);
WRAP_REQ_ARGS2(req, file, mode);
QUEUE_FS_TP_JOB(loop, req);
} else {
uv_fs_req_init_sync(loop, req, UV_FS_FCHMOD);
fs__fchmod(req, file, mode);
}

return 0;
}


int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
double mtime, uv_fs_cb cb) {
if (cb) {
Expand Down
8 changes: 8 additions & 0 deletions src/win/winapi.c
Expand Up @@ -28,6 +28,7 @@

sRtlNtStatusToDosError pRtlNtStatusToDosError;
sNtQueryInformationFile pNtQueryInformationFile;
sNtSetInformationFile pNtSetInformationFile;
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;

Expand Down Expand Up @@ -55,6 +56,13 @@ void uv_winapi_init() {
uv_fatal_error(GetLastError(), "GetProcAddress");
}

pNtSetInformationFile = (sNtSetInformationFile) GetProcAddress(
ntdll_module,
"NtSetInformationFile");
if (pNtSetInformationFile == NULL) {
uv_fatal_error(GetLastError(), "GetProcAddress");
}

kernel32_module = GetModuleHandleA("kernel32.dll");
if (kernel32_module == NULL) {
uv_fatal_error(GetLastError(), "GetModuleHandleA");
Expand Down
15 changes: 15 additions & 0 deletions src/win/winapi.h
Expand Up @@ -4096,6 +4096,14 @@ typedef struct _FILE_PIPE_LOCAL_INFORMATION {
ULONG NamedPipeEnd;
} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;

typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
DWORD FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;

typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation,
Expand Down Expand Up @@ -4165,6 +4173,12 @@ typedef NTSTATUS (NTAPI *sNtQueryInformationFile)
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass);

typedef NTSTATUS (NTAPI *sNtSetInformationFile)
(HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass);

/*
* Kernel32 headers
Expand Down Expand Up @@ -4197,6 +4211,7 @@ typedef BOOL (WINAPI* sSetFileCompletionNotificationModes)
/* Ntapi function pointers */
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
extern sNtQueryInformationFile pNtQueryInformationFile;
extern sNtSetInformationFile pNtSetInformationFile;


/* Kernel32 function pointers */
Expand Down

0 comments on commit cf5ed86

Please sign in to comment.