Windows: Readlink improvements (#6745)
* Windows: Use readlink emulation for File.readlink This fixes readlink emulation for the ERROR_MORE_DATA case and general error reporting. It now releases GVL while readlink IO operation. The dedicated rb_readlink was introduced in commit 2ffb87995a33cdc7ba609a4b867f03f18da0c3b3 in order to improve encoding and buffer allocation. However the encoding issues are solved since ruby-3.0 switched to UTF-8 and the buffer allocation will be improved in a later commit. * Windows: Increase the default buffer size for reparse point info So far nearly all queries of reparse points needed two attempts to get enough buffer. * Windows: Remove declaration of rb_w32_wreadlink It was removed in commit 2f6fdd3aebdee2ce04d003b206f6da78120e8235
This commit is contained in:
parent
71e668e633
commit
7b1d23fd29
Notes:
git
2022-11-17 09:58:21 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>
4
file.c
4
file.c
@ -115,6 +115,8 @@ int flock(int, int);
|
|||||||
# define link(f, t) rb_w32_ulink((f), (t))
|
# define link(f, t) rb_w32_ulink((f), (t))
|
||||||
# undef unlink
|
# undef unlink
|
||||||
# define unlink(p) rb_w32_uunlink(p)
|
# define unlink(p) rb_w32_uunlink(p)
|
||||||
|
# undef readlink
|
||||||
|
# define readlink(f, t, l) rb_w32_ureadlink((f), (t), (l))
|
||||||
# undef rename
|
# undef rename
|
||||||
# define rename(f, t) rb_w32_urename((f), (t))
|
# define rename(f, t) rb_w32_urename((f), (t))
|
||||||
# undef symlink
|
# undef symlink
|
||||||
@ -3152,7 +3154,6 @@ rb_file_s_readlink(VALUE klass, VALUE path)
|
|||||||
return rb_readlink(path, rb_filesystem_encoding());
|
return rb_readlink(path, rb_filesystem_encoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
struct readlink_arg {
|
struct readlink_arg {
|
||||||
const char *path;
|
const char *path;
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -3208,7 +3209,6 @@ rb_readlink(VALUE path, rb_encoding *enc)
|
|||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#define rb_file_s_readlink rb_f_notimplement
|
#define rb_file_s_readlink rb_f_notimplement
|
||||||
#endif
|
#endif
|
||||||
|
@ -302,7 +302,6 @@ extern DWORD rb_w32_osver(void);
|
|||||||
extern int rb_w32_uchown(const char *, int, int);
|
extern int rb_w32_uchown(const char *, int, int);
|
||||||
extern int rb_w32_ulink(const char *, const char *);
|
extern int rb_w32_ulink(const char *, const char *);
|
||||||
extern ssize_t rb_w32_ureadlink(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 rb_w32_usymlink(const char *src, const char *link);
|
extern int rb_w32_usymlink(const char *src, const char *link);
|
||||||
extern int gettimeofday(struct timeval *, struct timezone *);
|
extern int gettimeofday(struct timeval *, struct timezone *);
|
||||||
extern int clock_gettime(clockid_t, struct timespec *);
|
extern int clock_gettime(clockid_t, struct timespec *);
|
||||||
|
44
win32/file.c
44
win32/file.c
@ -591,50 +591,6 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
|
||||||
rb_readlink(VALUE path, rb_encoding *resultenc)
|
|
||||||
{
|
|
||||||
DWORD len;
|
|
||||||
VALUE wtmp = 0, wpathbuf, str;
|
|
||||||
rb_w32_reparse_buffer_t rbuf, *rp = &rbuf;
|
|
||||||
WCHAR *wpath, *wbuf;
|
|
||||||
rb_encoding *enc;
|
|
||||||
UINT cp, path_cp;
|
|
||||||
int e;
|
|
||||||
|
|
||||||
FilePathValue(path);
|
|
||||||
enc = rb_enc_get(path);
|
|
||||||
cp = path_cp = code_page(enc);
|
|
||||||
if (cp == INVALID_CODE_PAGE) {
|
|
||||||
path = fix_string_encoding(path, enc);
|
|
||||||
cp = CP_UTF8;
|
|
||||||
}
|
|
||||||
len = MultiByteToWideChar(cp, 0, RSTRING_PTR(path), RSTRING_LEN(path), NULL, 0);
|
|
||||||
wpath = ALLOCV_N(WCHAR, wpathbuf, len+1);
|
|
||||||
MultiByteToWideChar(cp, 0, RSTRING_PTR(path), RSTRING_LEN(path), wpath, len);
|
|
||||||
wpath[len] = L'\0';
|
|
||||||
e = rb_w32_read_reparse_point(wpath, rp, sizeof(rbuf), &wbuf, &len);
|
|
||||||
if (e == ERROR_MORE_DATA) {
|
|
||||||
size_t size = rb_w32_reparse_buffer_size(len + 1);
|
|
||||||
rp = ALLOCV(wtmp, size);
|
|
||||||
e = rb_w32_read_reparse_point(wpath, rp, size, &wbuf, &len);
|
|
||||||
}
|
|
||||||
ALLOCV_END(wpathbuf);
|
|
||||||
if (e) {
|
|
||||||
ALLOCV_END(wtmp);
|
|
||||||
if (e != -1)
|
|
||||||
rb_syserr_fail_path(rb_w32_map_errno(e), path);
|
|
||||||
else /* not symlink; maybe volume mount point */
|
|
||||||
rb_syserr_fail_path(EINVAL, path);
|
|
||||||
}
|
|
||||||
enc = resultenc;
|
|
||||||
path_cp = code_page(enc);
|
|
||||||
len = lstrlenW(wbuf);
|
|
||||||
str = append_wstr(rb_enc_str_new(0, 0, enc), wbuf, len, path_cp, enc);
|
|
||||||
ALLOCV_END(wtmp);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_file_load_ok(const char *path)
|
rb_file_load_ok(const char *path)
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
#ifndef RUBY_WIN32_FILE_H
|
#ifndef RUBY_WIN32_FILE_H
|
||||||
#define RUBY_WIN32_FILE_H
|
#define RUBY_WIN32_FILE_H
|
||||||
|
|
||||||
#define MAX_REPARSE_PATH_LEN 4092
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MINIMUM_REPARSE_BUFFER_PATH_LEN = 4
|
MINIMUM_REPARSE_BUFFER_PATH_LEN = 100
|
||||||
};
|
};
|
||||||
/* License: Ruby's */
|
/* License: Ruby's */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -18,14 +16,14 @@ typedef struct {
|
|||||||
USHORT PrintNameOffset;
|
USHORT PrintNameOffset;
|
||||||
USHORT PrintNameLength;
|
USHORT PrintNameLength;
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
WCHAR PathBuffer[4];
|
WCHAR PathBuffer[MINIMUM_REPARSE_BUFFER_PATH_LEN];
|
||||||
} SymbolicLinkReparseBuffer;
|
} SymbolicLinkReparseBuffer;
|
||||||
struct {
|
struct {
|
||||||
USHORT SubstituteNameOffset;
|
USHORT SubstituteNameOffset;
|
||||||
USHORT SubstituteNameLength;
|
USHORT SubstituteNameLength;
|
||||||
USHORT PrintNameOffset;
|
USHORT PrintNameOffset;
|
||||||
USHORT PrintNameLength;
|
USHORT PrintNameLength;
|
||||||
WCHAR PathBuffer[4];
|
WCHAR PathBuffer[MINIMUM_REPARSE_BUFFER_PATH_LEN];
|
||||||
} MountPointReparseBuffer;
|
} MountPointReparseBuffer;
|
||||||
};
|
};
|
||||||
} rb_w32_reparse_buffer_t;
|
} rb_w32_reparse_buffer_t;
|
||||||
|
@ -5144,32 +5144,35 @@ rb_w32_read_reparse_point(const WCHAR *path, rb_w32_reparse_buffer_t *rp,
|
|||||||
static ssize_t
|
static ssize_t
|
||||||
w32_readlink(UINT cp, const char *path, char *buf, size_t bufsize)
|
w32_readlink(UINT cp, const char *path, char *buf, size_t bufsize)
|
||||||
{
|
{
|
||||||
VALUE wtmp;
|
VALUE rp_buf, rp_buf_bigger = 0;
|
||||||
DWORD len = MultiByteToWideChar(cp, 0, path, -1, NULL, 0);
|
DWORD len = MultiByteToWideChar(cp, 0, path, -1, NULL, 0);
|
||||||
size_t size = rb_w32_reparse_buffer_size(len);
|
size_t size = rb_w32_reparse_buffer_size(bufsize);
|
||||||
WCHAR *wname, *wpath = ALLOCV(wtmp, size + sizeof(WCHAR) * len);
|
WCHAR *wname;
|
||||||
|
WCHAR *wpath = ALLOCV(rp_buf, sizeof(WCHAR) * len + size);
|
||||||
rb_w32_reparse_buffer_t *rp = (void *)(wpath + len);
|
rb_w32_reparse_buffer_t *rp = (void *)(wpath + len);
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
int e;
|
int e;
|
||||||
|
|
||||||
MultiByteToWideChar(cp, 0, path, -1, wpath, len);
|
MultiByteToWideChar(cp, 0, path, -1, wpath, len);
|
||||||
e = rb_w32_read_reparse_point(wpath, rp, size, &wname, &len);
|
e = rb_w32_read_reparse_point(wpath, rp, size, &wname, &len);
|
||||||
if (e && e != ERROR_MORE_DATA) {
|
if (e == ERROR_MORE_DATA) {
|
||||||
ALLOCV_END(wtmp);
|
size = rb_w32_reparse_buffer_size(len + 1);
|
||||||
errno = map_errno(e);
|
rp = ALLOCV(rp_buf_bigger, size);
|
||||||
|
e = rb_w32_read_reparse_point(wpath, rp, size, &wname, &len);
|
||||||
|
}
|
||||||
|
if (e) {
|
||||||
|
ALLOCV_END(rp_buf);
|
||||||
|
ALLOCV_END(rp_buf_bigger);
|
||||||
|
errno = e == -1 ? EINVAL : map_errno(e);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
len = lstrlenW(wname) + 1;
|
len = lstrlenW(wname);
|
||||||
ret = WideCharToMultiByte(cp, 0, wname, len, buf, bufsize, NULL, NULL);
|
ret = WideCharToMultiByte(cp, 0, wname, len, buf, bufsize, NULL, NULL);
|
||||||
ALLOCV_END(wtmp);
|
ALLOCV_END(rp_buf);
|
||||||
if (e) {
|
ALLOCV_END(rp_buf_bigger);
|
||||||
|
if (!ret) {
|
||||||
ret = bufsize;
|
ret = bufsize;
|
||||||
}
|
}
|
||||||
else if (!ret) {
|
|
||||||
e = GetLastError();
|
|
||||||
errno = map_errno(e);
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user