Index: TSRM/tsrm_virtual_cwd.c =================================================================== RCS file: /repository/TSRM/tsrm_virtual_cwd.c,v retrieving revision 1.74.2.4 diff -u -r1.74.2.4 tsrm_virtual_cwd.c --- TSRM/tsrm_virtual_cwd.c 1 Jan 2006 12:50:00 -0000 1.74.2.4 +++ TSRM/tsrm_virtual_cwd.c 15 Jan 2006 17:24:05 -0000 @@ -746,6 +746,32 @@ } +#ifdef TSRM_WIN32 +/* convert a time_t to FILETIME (windows only) + Copied from Perl 5 code */ +static BOOL win_filetime_from_time(PFILETIME pFileTime, time_t Time) +{ + struct tm *pTM = localtime(&Time); + SYSTEMTIME SystemTime; + FILETIME LocalTime; + + if (!pTM) { + return FALSE; + } + + SystemTime.wYear = pTM->tm_year + 1900; + SystemTime.wMonth = pTM->tm_mon + 1; + SystemTime.wDay = pTM->tm_mday; + SystemTime.wHour = pTM->tm_hour; + SystemTime.wMinute = pTM->tm_min; + SystemTime.wSecond = pTM->tm_sec; + SystemTime.wMilliseconds = 0; + + return SystemTimeToFileTime(&SystemTime, &LocalTime) && + LocalFileTimeToFileTime(&LocalTime, pFileTime); +} +#endif + #if HAVE_UTIME CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC) { @@ -757,6 +783,48 @@ ret = utime(new_state.cwd, buf); + +#ifdef TSRM_WIN32 + /* utime fails with directories on windows, so we need this little hack + idea borrowed from Perl's code */ + if (ret == -1 && errno == EACCES) { + FILETIME atime, mtime; + time_t atime_t, mtime_t; + HANDLE handle; + + /* if NULL set access and modification time to current time */ + if (buf == NULL) { + atime_t = time(&mtime_t); + } else { + atime_t = buf->actime; + mtime_t = buf->modtime; + } + + /* fill in the FILETIME structures */ + if (win_filetime_from_time(&atime, atime_t) == FALSE || + win_filetime_from_time(&mtime, mtime_t) == FALSE) { + goto win_utime_error; + } + + /* open the directory and set the times */ + handle = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (handle == INVALID_HANDLE_VALUE) { + goto win_utime_error; + } + + if (SetFileTime(handle, NULL, &atime, &mtime)) { + ret = 0; /* there was no error */ + } else { + errno = GetLastError(); + } + CloseHandle(handle); + } +win_utime_error: +#endif + CWD_STATE_FREE(&new_state); return ret; }