summaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-03-23 05:40:48 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-03-23 05:40:48 +0000
commitf5b96e594c769cf309b70fd7736caaf90372a3b6 (patch)
tree8fa5fed653c81388e3c4b21c75dba9201db92f10 /win32
parent9da887cf57527f47146fc441f6d40e655aaadbb6 (diff)
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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50060 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'win32')
-rw-r--r--win32/Makefile.sub1
-rw-r--r--win32/win32.c101
2 files changed, 101 insertions, 1 deletions
diff --git a/win32/Makefile.sub b/win32/Makefile.sub
index 56cd86a14c..259193e0b2 100644
--- a/win32/Makefile.sub
+++ b/win32/Makefile.sub
@@ -708,6 +708,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
#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
diff --git a/win32/win32.c b/win32/win32.c
index 30b7e27fa0..a8ef299cc5 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -61,6 +61,7 @@ DWORD WINAPI GetFinalPathNameByHandleW(HANDLE, LPWSTR, DWORD, DWORD);
#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 *, UINT);
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)
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 stati64 *st)
}
/* 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)
{
@@ -5214,6 +5285,34 @@ w32_stati64(const char *path, struct stati64 *st, UINT cp)
/* 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
rb_w32_access(const char *path, int mode)
{
struct stati64 stat;