                       
    SYSTEMTIME st;
    time_t t;
    struct tm tm;

    GetLocalTime(&st);
    tm.tm_sec = st.wSecond;
    tm.tm_min = st.wMinute;
    tm.tm_hour = st.wHour;
    tm.tm_mday = st.wDay;
    tm.tm_mon = st.wMonth - 1;
    tm.tm_year = st.wYear - 1900;
    tm.tm_isdst = -1;
    t = mktime(&tm);
    tv->tv_sec = t;
    tv->tv_usec = st.wMilliseconds * 1000;

    return 0;
}

char *
win32_getcwd(buffer, size)
    char *buffer;
    int size;
{
    int length;
    char *bp;

    if (_getcwd(buffer, size) == NULL) {
        return NULL;
    }
    length = strlen(buffer);
    if (length >= size) {
        return NULL;
    }

    for (bp = buffer; *bp != '\0'; bp = CharNext(bp)) {
	if (*bp == '\\') {
	    *bp = '/';
	}
    }
    return buffer;
}

static char *
str_grow(struct RString *str, size_t new_size)
{
	char *p;

	p = realloc(str->ptr, new_size);
	if (p == NULL)
                rb_fatal("cannot grow string\n");

	str->len = new_size;
	str->ptr = p;

	return p;
}

int
chown(const char *path, int owner, int group)
{
	return 0;
}

#include <signal.h>
int
kill(int pid, int sig)
{
#if 1
	if ((unsigned int)pid == GetCurrentProcessId())
		return raise(sig);

	if (sig == 2 && pid > 0)
		if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, (DWORD)pid))
			return 0;

	return -1;
#else
	return 0;
#endif
}

int
link(char *from, char *to)
{
	return -1;
}

int
wait()
{
	return 0;
}

char *
win32_getenv(const char *name)
{
    static char *curitem = NULL;
    static DWORD curlen = 0;
    DWORD needlen;

    if (curitem == NULL || curlen == 0) {
	curlen = 512;
	curitem = ALLOC_N(char, curlen);
    }

    needlen = GetEnvironmentVariable(name, curitem, curlen);
    if (needlen != 0) {
	while (needlen > curlen) {
	    REALLOC_N(curitem, char, needlen);
	    curlen = needlen;
	    needlen = GetEnvironmentVariable(name, curitem, curlen);
	}
    }
    else {
	return NULL;
    }

    return curitem;
}

int
myrename(const char *oldpath, const char *newpath)
{
    int res = 0;
    int oldatts;
    int newatts;

    oldatts = GetFileAttributes(oldpath);
    newatts = GetFileAttributes(newpath);

    if (oldatts == -1) {
	errno = GetLastError();
	return -1;
    }

    if (newatts != -1 && newatts & FILE_ATTRIBUTE_READONLY)
	SetFileAttributesA(newpath, newatts & ~ FILE_ATTRIBUTE_READONLY);

    if (!MoveFile(oldpath, newpath))
	res = -1;

    if (res) {
	switch (GetLastError()) {
	  case ERROR_ALREADY_EXISTS:
	  case ERROR_FILE_EXISTS:
	    if (IsWinNT()) {
		if (MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
		    res = 0;
	    } else {
		for (;;) {
		    if (!DeleteFile(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND)
			break;
		    else if (MoveFile(oldpath, newpath)) {
			res = 0;
			break;
		    }
		}
	    }
	}
    }

    if (res)
	errno = GetLastError();
    else
	SetFileAttributes(newpath, oldatts);

    return res;
}

static int
isUNCRoot(const char *path)
{
    if (path[0] == '\\' && path[1] == '\\') {
	const char *p;
	for (p = path + 3; *p; p = CharNext(p)) {
	    if (*p == '\\')
		break;
	}
	if (p[0] && p[1]) {
	    for (p++; *p; p = CharNext(p)) {
		if (*p == '\\')
		    break;
	    }
	    if (!p[0] || !p[1])
		return 1;
	}
    }
    return 0;
}

int
win32_stat(const char *path, struct stat *st)
{
    const char *p;
    char *buf1 = ALLOCA_N(char, strlen(path) + 2);
    char *buf2 = ALLOCA_N(char, MAXPATHLEN);
    char *s;
    int len;
    int ret;

    for (p = path, s = buf1; *p; p++, s++) {
	if (*p == '/')
	    *s = '\\';
	else
	    *s = *p;
    }
    *s = '\0';
    len = s - buf1;
    if (!len || '\"' == *(--s)) {
	errno = ENOENT;
	return -1;
    }
    p = CharPrev(buf1, buf1 + len);

    if (isUNCRoot(buf1)) {
	if (*p != '\\')
	    strcat(buf1, "\\");
    } else if (*p == '\\' || *p == ':')
	strcat(buf1, ".");
    if (_fullpath(buf2, buf1, MAXPATHLEN)) {
	ret = stat(buf2, st);
	if (ret == 0) {
	    st->st_mode &= ~(S_IWGRP | S_IWOTH);
	}
	return ret;
    }
    else
	return -1;
}

static long
filetime_to_clock(FILETIME *ft)
{
    __int64 qw = ft->dwHighDateTime;
    qw <<= 32;
    qw |= ft->dwLowDateTime;
    qw /= 10000;  /* File time ticks at 0.1uS, clock at 1mS */
    return (long) qw;
}

int
mytimes(struct tms *tmbuf)
{
    FILETIME create, exit, kernel, user;

    if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
	tmbuf->tms_utime = filetime_to_clock(&user);
	tmbuf->tms_stime = filetime_to_clock(&kernel);
	tmbuf->tms_cutime = 0;
	tmbuf->tms_cstime = 0;
    }
    else {
	tmbuf->tms_utime = clock();
	tmbuf->tms_stime = 0;
	tmbuf->tms_cutime = 0;
	tmbuf->tms_cstime = 0;
    }
    retu