ruby-changes:37981
From: nobu <ko1@a...>
Date: Mon, 23 Mar 2015 17:36:26 +0900 (JST)
Subject: [ruby-changes:37981] nobu:r50062 (trunk): win32.c: readlink
nobu 2015-03-23 17:36:04 +0900 (Mon, 23 Mar 2015) New Revision: 50062 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50062 Log: win32.c: readlink * win32/win32.c (wreadlink, rb_w32_ureadlink): implement readlink(). Modified files: trunk/ChangeLog trunk/configure.in trunk/include/ruby/win32.h trunk/win32/Makefile.sub trunk/win32/win32.c Index: include/ruby/win32.h =================================================================== --- include/ruby/win32.h (revision 50061) +++ include/ruby/win32.h (revision 50062) @@ -316,6 +316,9 @@ extern int chown(const char *, int, int) https://github.com/ruby/ruby/blob/trunk/include/ruby/win32.h#L316 extern int rb_w32_uchown(const char *, int, int); extern int link(const char *, const char *); extern int rb_w32_ulink(const char *, const char *); +extern ssize_t readlink(const char *, char *, size_t); +extern ssize_t rb_w32_ureadlink(const char *, char *, size_t); +extern ssize_t rb_w32_wreadlink(const WCHAR *, WCHAR *, size_t); extern int gettimeofday(struct timeval *, struct timezone *); extern int clock_gettime(clockid_t, struct timespec *); extern int clock_getres(clockid_t, struct timespec *); Index: configure.in =================================================================== --- configure.in (revision 50061) +++ configure.in (revision 50062) @@ -1104,6 +1104,7 @@ main() https://github.com/ruby/ruby/blob/trunk/configure.in#L1104 ac_cv_func_isnan=yes ac_cv_func_finite=yes ac_cv_func_link=yes + ac_cv_func_readlink=yes ac_cv_lib_crypt_crypt=no ac_cv_func_getpgrp_void=no ac_cv_func_memcmp_working=yes Index: ChangeLog =================================================================== --- ChangeLog (revision 50061) +++ ChangeLog (revision 50062) @@ -1,3 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Mar 23 17:36:00 2015 Nobuyoshi Nakada <nobu@r...> + + * win32/win32.c (wreadlink, rb_w32_ureadlink): implement readlink(). + Mon Mar 23 14:40:45 2015 Nobuyoshi Nakada <nobu@r...> * win32/win32.c (winnt_stat): stat with following symbolic links. Index: win32/win32.c =================================================================== --- win32/win32.c (revision 50061) +++ win32/win32.c (revision 50062) @@ -4679,6 +4679,116 @@ link(const char *from, const char *to) https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L4679 } /* License: Ruby's */ +ssize_t +rb_w32_wreadlink(const WCHAR *path, WCHAR *buf, size_t bufsize) +{ + struct { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[MAXPATHLEN * 2]; + } SymbolicLinkReparseBuffer; + } rp; + HANDLE f; + DWORD ret; + int e = 0; + + typedef BOOL (WINAPI *device_io_control_func)(HANDLE, DWORD, LPVOID, + DWORD, LPVOID, DWORD, + LPDWORD, LPOVERLAPPED); + static device_io_control_func device_io_control = (device_io_control_func)-1; + + if (device_io_control == (device_io_control_func)-1) { + device_io_control = (device_io_control_func) + get_proc_address("kernel32", "DeviceIoControl", NULL); + } + if (!device_io_control) { + errno = ENOSYS; + return -1; + } + + f = CreateFileW(path, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT, + NULL); + if (f == INVALID_HANDLE_VALUE) { + errno = map_errno(GetLastError()); + return -1; + } + + if (!device_io_control(f, FSCTL_GET_REPARSE_POINT, NULL, 0, + &rp, sizeof(rp), &ret, NULL)) { + e = map_errno(GetLastError()); + } + else if (rp.ReparseTag != IO_REPARSE_TAG_SYMLINK){ + e = EINVAL; + } + else { + void *name = ((char *)rp.SymbolicLinkReparseBuffer.PathBuffer + + rp.SymbolicLinkReparseBuffer.PrintNameOffset); + ret = rp.SymbolicLinkReparseBuffer.PrintNameLength; + ((WCHAR *)name)[ret/sizeof(WCHAR)] = L'\0'; + translate_wchar(name, L'\\', L'/'); + bufsize *= sizeof(WCHAR); + memcpy(buf, name, ret > bufsize ? bufsize : ret); + } + + CloseHandle(f); + if (e) { + errno = e; + return -1; + } + return ret / sizeof(WCHAR); +} + +/* License: Ruby's */ +static ssize_t +w32_readlink(UINT cp, const char *path, char *buf, size_t bufsize) +{ + WCHAR *wpath; + WCHAR wbuf[MAXPATHLEN]; + ssize_t ret; + + wpath = mbstr_to_wstr(cp, path, -1, NULL); + if (!wpath) return -1; + ret = rb_w32_wreadlink(wpath, wbuf, MAXPATHLEN); + free(wpath); + if (ret < 0) return ret; + ret = WideCharToMultiByte(cp, 0, wbuf, ret, buf, bufsize, NULL, NULL); + if (!ret) { + int e = GetLastError(); + if (e == ERROR_INSUFFICIENT_BUFFER) { + ret = bufsize; + } + else { + errno = map_errno(e); + ret = -1; + } + } + return ret; +} + +/* License: Ruby's */ +ssize_t +rb_w32_ureadlink(const char *path, char *buf, size_t bufsize) +{ + return w32_readlink(CP_UTF8, path, buf, bufsize); +} + +/* License: Ruby's */ +ssize_t +readlink(const char *path, char *buf, size_t bufsize) +{ + return w32_readlink(filecp(), path, buf, bufsize); +} + +/* License: Ruby's */ int wait(int *status) { Index: win32/Makefile.sub =================================================================== --- win32/Makefile.sub (revision 50061) +++ win32/Makefile.sub (revision 50062) @@ -712,6 +712,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/ https://github.com/ruby/ruby/blob/trunk/win32/Makefile.sub#L712 #define HAVE_TIMES 1 #define HAVE_FCNTL 1 #define HAVE_LINK 1 +#define HAVE_READLINK 1 #define HAVE__SETJMP 1 #define HAVE_TELLDIR 1 #define HAVE_SEEKDIR 1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/