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))
|
||||
# undef unlink
|
||||
# define unlink(p) rb_w32_uunlink(p)
|
||||
# undef readlink
|
||||
# define readlink(f, t, l) rb_w32_ureadlink((f), (t), (l))
|
||||
# undef rename
|
||||
# define rename(f, t) rb_w32_urename((f), (t))
|
||||
# undef symlink
|
||||
@ -3152,7 +3154,6 @@ rb_file_s_readlink(VALUE klass, VALUE path)
|
||||
return rb_readlink(path, rb_filesystem_encoding());
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
struct readlink_arg {
|
||||
const char *path;
|
||||
char *buf;
|
||||
@ -3208,7 +3209,6 @@ rb_readlink(VALUE path, rb_encoding *enc)
|
||||
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#define rb_file_s_readlink rb_f_notimplement
|
||||
#endif
|
||||
|
@ -302,7 +302,6 @@ extern DWORD rb_w32_osver(void);
|
||||
extern int rb_w32_uchown(const char *, int, int);
|
||||
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_wreadlink(const WCHAR *, WCHAR *, size_t);
|
||||
extern int rb_w32_usymlink(const char *src, const char *link);
|
||||
extern int gettimeofday(struct timeval *, struct timezone *);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
rb_file_load_ok(const char *path)
|
||||
{
|
||||
|
@ -1,10 +1,8 @@
|
||||
#ifndef RUBY_WIN32_FILE_H
|
||||
#define RUBY_WIN32_FILE_H
|
||||
|
||||
#define MAX_REPARSE_PATH_LEN 4092
|
||||
|
||||
enum {
|
||||
MINIMUM_REPARSE_BUFFER_PATH_LEN = 4
|
||||
MINIMUM_REPARSE_BUFFER_PATH_LEN = 100
|
||||
};
|
||||
/* License: Ruby's */
|
||||
typedef struct {
|
||||
@ -18,14 +16,14 @@ typedef struct {
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
ULONG Flags;
|
||||
WCHAR PathBuffer[4];
|
||||
WCHAR PathBuffer[MINIMUM_REPARSE_BUFFER_PATH_LEN];
|
||||
} SymbolicLinkReparseBuffer;
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[4];
|
||||
WCHAR PathBuffer[MINIMUM_REPARSE_BUFFER_PATH_LEN];
|
||||
} MountPointReparseBuffer;
|
||||
};
|
||||
} 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
|
||||
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);
|
||||
size_t size = rb_w32_reparse_buffer_size(len);
|
||||
WCHAR *wname, *wpath = ALLOCV(wtmp, size + sizeof(WCHAR) * len);
|
||||
size_t size = rb_w32_reparse_buffer_size(bufsize);
|
||||
WCHAR *wname;
|
||||
WCHAR *wpath = ALLOCV(rp_buf, sizeof(WCHAR) * len + size);
|
||||
rb_w32_reparse_buffer_t *rp = (void *)(wpath + len);
|
||||
ssize_t ret;
|
||||
int e;
|
||||
|
||||
MultiByteToWideChar(cp, 0, path, -1, wpath, len);
|
||||
e = rb_w32_read_reparse_point(wpath, rp, size, &wname, &len);
|
||||
if (e && e != ERROR_MORE_DATA) {
|
||||
ALLOCV_END(wtmp);
|
||||
errno = map_errno(e);
|
||||
if (e == ERROR_MORE_DATA) {
|
||||
size = rb_w32_reparse_buffer_size(len + 1);
|
||||
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;
|
||||
}
|
||||
len = lstrlenW(wname) + 1;
|
||||
len = lstrlenW(wname);
|
||||
ret = WideCharToMultiByte(cp, 0, wname, len, buf, bufsize, NULL, NULL);
|
||||
ALLOCV_END(wtmp);
|
||||
if (e) {
|
||||
ALLOCV_END(rp_buf);
|
||||
ALLOCV_END(rp_buf_bigger);
|
||||
if (!ret) {
|
||||
ret = bufsize;
|
||||
}
|
||||
else if (!ret) {
|
||||
e = GetLastError();
|
||||
errno = map_errno(e);
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user