Index: win32/win32.c =================================================================== --- win32/win32.c (revision 37316) +++ win32/win32.c (working copy) @@ -6195,6 +6195,14 @@ rb_w32_write_console(uintptr_t strarg, i } /* License: Ruby's */ +typedef enum utime_mode utime_mode_t; + +enum utime_mode { + M_SYMLINK_FOLLOW = 0, + M_SYMLINK_NOFOLLOW +}; + +/* License: Ruby's */ static int unixtime_to_filetime(time_t time, FILETIME *ft) { @@ -6208,11 +6216,12 @@ unixtime_to_filetime(time_t time, FILETI /* License: Ruby's */ static int -wutime(const WCHAR *path, const struct utimbuf *times) +wutime(const WCHAR *path, const struct utimbuf *times, utime_mode_t mode) { HANDLE hFile; FILETIME atime, mtime; struct stati64 stat; + int flags; int ret = 0; if (wstati64(path, &stat)) { @@ -6232,12 +6241,16 @@ wutime(const WCHAR *path, const struct u mtime = atime; } + flags = FILE_FLAG_BACKUP_SEMANTICS; + if (mode == M_SYMLINK_NOFOLLOW) + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + RUBY_CRITICAL({ const DWORD attr = GetFileAttributesW(path); if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) SetFileAttributesW(path, attr & ~FILE_ATTRIBUTE_READONLY); hFile = CreateFileW(path, GENERIC_WRITE, 0, 0, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, 0); + flags, 0); if (hFile == INVALID_HANDLE_VALUE) { errno = map_errno(GetLastError()); ret = -1; @@ -6258,33 +6271,61 @@ wutime(const WCHAR *path, const struct u /* License: Ruby's */ int -rb_w32_uutime(const char *path, const struct utimbuf *times) +uutime_internal(const char *path, const struct utimbuf *times, utime_mode_t mode) { WCHAR *wpath; int ret; if (!(wpath = utf8_to_wstr(path, NULL))) return -1; - ret = wutime(wpath, times); + ret = wutime(wpath, times, mode); free(wpath); return ret; } /* License: Ruby's */ int -rb_w32_utime(const char *path, const struct utimbuf *times) +utime_internal(const char *path, const struct utimbuf *times, utime_mode_t mode) { WCHAR *wpath; int ret; if (!(wpath = filecp_to_wstr(path, NULL))) return -1; - ret = wutime(wpath, times); + ret = wutime(wpath, times, mode); free(wpath); return ret; } /* License: Ruby's */ +int +rb_w32_uutime(const char *path, const struct utimbuf *times) +{ + return uutime_internal(path, times, M_SYMLINK_FOLLOW); +} + +/* License: Ruby's */ +int +rb_w32_utime(const char *path, const struct utimbuf *times) +{ + return utime_internal(path, times, M_SYMLINK_FOLLOW); +} + +/* License: Ruby's */ +int +rb_w32_luutime(const char *path, const struct utimbuf *times) +{ + return uutime_internal(path, times, M_SYMLINK_NOFOLLOW); +} + +/* License: Ruby's */ +int +rb_w32_lutime(const char *path, const struct utimbuf *times) +{ + return utime_internal(path, times, M_SYMLINK_NOFOLLOW); +} + +/* License: Ruby's */ int rb_w32_uchdir(const char *path) { Index: file.c =================================================================== --- file.c (revision 37316) +++ file.c (working copy) @@ -92,6 +92,8 @@ int flock(int, int); #define chown(p, o, g) rb_w32_uchown((p), (o), (g)) #undef utime #define utime(p, t) rb_w32_uutime((p), (t)) +#undef lutime +#define lutime(p, t) rb_w32_luutime((p), (t)) #undef link #define link(f, t) rb_w32_ulink((f), (t)) #undef unlink