ruby-changes:37979
From: nobu <ko1@a...>
Date: Mon, 23 Mar 2015 14:41:06 +0900 (JST)
Subject: [ruby-changes:37979] nobu:r50060 (trunk): win32.c: w32_lstati64
nobu 2015-03-23 14:40:48 +0900 (Mon, 23 Mar 2015) New Revision: 50060 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50060 Log: win32.c: w32_lstati64 * win32/win32.c (winnt_stat): stat with following symbolic links. * win32/win32.c (winnt_lstat): rename old winnt_stat, which does not follow symbolic links. Modified files: trunk/ChangeLog trunk/configure.in trunk/dir.c trunk/file.c trunk/include/ruby/win32.h trunk/win32/Makefile.sub trunk/win32/win32.c Index: include/ruby/win32.h =================================================================== --- include/ruby/win32.h (revision 50059) +++ include/ruby/win32.h (revision 50060) @@ -215,6 +215,7 @@ typedef int clockid_t; https://github.com/ruby/ruby/blob/trunk/include/ruby/win32.h#L215 extern int rb_w32_stat(const char *, struct stat *); extern int rb_w32_fstat(int, struct stat *); #endif +#define lstat(path,st) rb_w32_lstati64(path,st) #define access(path,mode) rb_w32_access(path,mode) #define strcasecmp _stricmp @@ -343,6 +344,8 @@ extern int rb_w32_uunlink(const char *); https://github.com/ruby/ruby/blob/trunk/include/ruby/win32.h#L344 extern int rb_w32_uchmod(const char *, int); extern int rb_w32_stati64(const char *, struct stati64 *); extern int rb_w32_ustati64(const char *, struct stati64 *); +extern int rb_w32_lstati64(const char *, struct stati64 *); +extern int rb_w32_ulstati64(const char *, struct stati64 *); extern int rb_w32_access(const char *, int); extern int rb_w32_uaccess(const char *, int); extern char rb_w32_fd_is_text(int); Index: configure.in =================================================================== --- configure.in (revision 50059) +++ configure.in (revision 50060) @@ -1094,6 +1094,7 @@ main() https://github.com/ruby/ruby/blob/trunk/configure.in#L1094 ac_cv_header_sys_time_h=no ac_cv_header_sys_times_h=no ac_cv_header_sys_socket_h=no + ac_cv_func_lstat=yes ac_cv_func_times=yes ac_cv_func_waitpid=yes ac_cv_func_fsync=yes Index: ChangeLog =================================================================== --- ChangeLog (revision 50059) +++ ChangeLog (revision 50060) @@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Mar 23 14:40:45 2015 Nobuyoshi Nakada <nobu@r...> + + * win32/win32.c (winnt_stat): stat with following symbolic links. + + * win32/win32.c (winnt_lstat): rename old winnt_stat, which does + not follow symbolic links. + Mon Mar 23 02:03:28 2015 Nobuyoshi Nakada <nobu@r...> * marshal.c (r_symreal): register symbol names as strings first so Index: dir.c =================================================================== --- dir.c (revision 50059) +++ dir.c (revision 50060) @@ -1135,6 +1135,8 @@ sys_enc_warning_in(const char *func, con https://github.com/ruby/ruby/blob/trunk/dir.c#L1135 #ifdef _WIN32 #define STAT(p, s) rb_w32_ustati64((p), (s)) +#undef lstat +#define lstat(p, s) rb_w32_ulstati64((p), (s)) #else #define STAT(p, s) stat((p), (s)) #endif Index: win32/win32.c =================================================================== --- win32/win32.c (revision 50059) +++ win32/win32.c (revision 50060) @@ -61,6 +61,7 @@ DWORD WINAPI GetFinalPathNameByHandleW(H https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L61 #endif static int w32_stati64(const char *path, struct stati64 *st, UINT cp); +static int w32_lstati64(const char *path, struct stati64 *st, UINT cp); static char *w32_getenv(const char *name, UINT cp); #undef getenv @@ -111,6 +112,7 @@ static int has_redirection(const char *, https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L112 int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout); static int rb_w32_open_osfhandle(intptr_t osfhandle, int flags); static int wstati64(const WCHAR *path, struct stati64 *st); +static int wlstati64(const WCHAR *path, struct stati64 *st); VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc); int ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc); @@ -5079,17 +5081,63 @@ path_drive(const WCHAR *path) https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L5081 towupper(path[0]) - L'A' : _getdrive() - 1; } +static const WCHAR namespace_prefix[] = {L'\\', L'\\', L'?', L'\\'}; + /* License: Ruby's */ static int winnt_stat(const WCHAR *path, struct stati64 *st) { + HANDLE f; + + typedef DWORD (WINAPI *get_final_path_func)(HANDLE, WCHAR*, DWORD, DWORD); + static get_final_path_func get_final_path = (get_final_path_func)-1; + + if (get_final_path == (get_final_path_func)-1) { + get_final_path = (get_final_path_func) + get_proc_address(NULL, "GetFinalPathNameByHandleW", NULL); + } + + memset(st, 0, sizeof(*st)); + f = CreateFileW(path, 0, 0, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (f != INVALID_HANDLE_VALUE) { + WCHAR finalname[MAX_PATH]; + const DWORD attr = stati64_handle(f, st); + const DWORD len = get_final_path ? + get_final_path(f, finalname, numberof(finalname), 0) : 0; + CloseHandle(f); + if (attr & FILE_ATTRIBUTE_DIRECTORY) { + if (check_valid_dir(path)) return -1; + } + st->st_mode = fileattr_to_unixmode(attr, path); + if (len) { + finalname[len] = L'\0'; + path = finalname; + if (wcsncmp(path, namespace_prefix, numberof(namespace_prefix)) == 0) + path += numberof(namespace_prefix); + } + } + else { + if (stat_by_find(path, st)) return -1; + } + + st->st_dev = st->st_rdev = path_drive(path); + + return 0; +} + +/* License: Ruby's */ +static int +winnt_lstat(const WCHAR *path, struct stati64 *st) +{ WIN32_FILE_ATTRIBUTE_DATA wfa; const WCHAR *p = path; memset(st, 0, sizeof(*st)); st->st_nlink = 1; - if (wcsncmp(p, L"\\\\?\\", 4) == 0) p += 4; + if (wcsncmp(p, namespace_prefix, numberof(namespace_prefix)) == 0) + p += numberof(namespace_prefix); if (wcspbrk(p, L"?*")) { errno = ENOENT; return -1; @@ -5151,6 +5199,29 @@ wstati64(const WCHAR *path, struct stati https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L5199 } /* License: Ruby's */ +static int +wlstati64(const WCHAR *path, struct stati64 *st) +{ + WCHAR *buf1; + int ret, size; + VALUE v; + + if (!path || !st) { + errno = EFAULT; + return -1; + } + size = lstrlenW(path) + 2; + buf1 = ALLOCV_N(WCHAR, v, size); + if (!(path = name_for_stat(buf1, path))) + return -1; + ret = winnt_lstat(path, st); + if (v) + ALLOCV_END(v); + + return ret; +} + +/* License: Ruby's */ static WCHAR * name_for_stat(WCHAR *buf1, const WCHAR *path) { @@ -5211,6 +5282,34 @@ w32_stati64(const char *path, struct sta https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L5282 free(wpath); return ret; } + +/* License: Ruby's */ +int +rb_w32_ulstati64(const char *path, struct stati64 *st) +{ + return w32_lstati64(path, st, CP_UTF8); +} + +/* License: Ruby's */ +int +rb_w32_lstati64(const char *path, struct stati64 *st) +{ + return w32_lstati64(path, st, filecp()); +} + +/* License: Ruby's */ +static int +w32_lstati64(const char *path, struct stati64 *st, UINT cp) +{ + WCHAR *wpath; + int ret; + + if (!(wpath = mbstr_to_wstr(cp, path, -1, NULL))) + return -1; + ret = wlstati64(wpath, st); + free(wpath); + return ret; +} /* License: Ruby's */ int Index: win32/Makefile.sub =================================================================== --- win32/Makefile.sub (revision 50059) +++ win32/Makefile.sub (revision 50060) @@ -708,6 +708,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/ https://github.com/ruby/ruby/blob/trunk/win32/Makefile.sub#L708 #define HAVE_GETCWD 1 #define HAVE_TRUNCATE 1 #define HAVE_FTRUNCATE 1 +#define HAVE_LSTAT 1 #define HAVE_TIMES 1 #define HAVE_FCNTL 1 #define HAVE_LINK 1 Index: file.c =================================================================== --- file.c (revision 50059) +++ file.c (revision 50060) @@ -95,7 +95,7 @@ int flock(int, int); https://github.com/ruby/ruby/blob/trunk/file.c#L95 #ifdef _WIN32 #define STAT(p, s) rb_w32_ustati64((p), (s)) #undef lstat -#define lstat(p, s) rb_w32_ustati64((p), (s)) +#define lstat(p, s) rb_w32_ulstati64((p), (s)) #undef access #define access(p, m) rb_w32_uaccess((p), (m)) #undef chmod -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/