[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]