1#if defined(__MINGW32__)
3# define MINGW_HAS_SECURE_API 1
13#ifndef INVALID_FILE_ATTRIBUTES
14# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
18static struct code_page_table {
23#define IS_DIR_SEPARATOR_P(c) (c == L'\\' || c == L'/')
24#define IS_DIR_UNC_P(c) (IS_DIR_SEPARATOR_P(c[0]) && IS_DIR_SEPARATOR_P(c[1]))
26IS_ABSOLUTE_PATH_P(
const WCHAR *
path,
size_t len)
36#define INVALID_CODE_PAGE 51932
37#define PATH_BUFFER_SIZE MAX_PATH * 2
39#define insecure_obj_p(obj, level) ((level) > 0 && OBJ_TAINTED(obj))
42#define system_code_page rb_w32_filecp
43#define mbstr_to_wstr rb_w32_mbstr_to_wstr
44#define wstr_to_mbstr rb_w32_wstr_to_mbstr
47replace_wchar(
wchar_t *s,
int find,
int replace)
58remove_invalid_alternative_data(
wchar_t *wfullpath,
size_t size)
60 static const wchar_t prime[] =
L":$DATA";
61 enum { prime_len = (
sizeof(prime) /
sizeof(
wchar_t)) -1 };
63 if (
size <= prime_len || _wcsnicmp(wfullpath +
size - prime_len, prime, prime_len) != 0)
68 if (wfullpath[
size - (prime_len + 1)] ==
':') {
70 size -= prime_len + 1;
71 wfullpath[
size] =
L'\0';
75 wchar_t *pos = wfullpath +
size - (prime_len + 1);
79 wfullpath[
size] =
L'\0';
93 const char *
n = (
const char *)
name;
95 int code_page =
atoi(
n + 2);
97 struct code_page_table *cp = (
struct code_page_table *)
arg;
98 unsigned int count = cp->count;
99 USHORT *table = cp->table;
102 count = (((idx + 4) & ~31) | 28);
109 table[idx] = (USHORT)code_page;
138 if (0 <= enc_idx && (
unsigned int)enc_idx < rb_code_page.count)
139 return rb_code_page.table[enc_idx];
144#define fix_string_encoding(str, encoding) rb_str_conv_enc((str), (encoding), rb_utf8_encoding())
151replace_to_long_name(
wchar_t **wfullpath,
size_t size,
size_t buffer_size)
153 WIN32_FIND_DATAW find_data;
165 size_t const max_short_name_size = 8 + 1 + 3;
166 size_t const max_extension_size = 3;
167 size_t path_len = 1, extension_len = 0;
168 wchar_t *pos = *wfullpath;
170 if (
size == 3 && pos[1] ==
L':' && pos[2] ==
L'\\' && pos[3] ==
L'\0') {
176 if (wcspbrk(pos,
L"*?")) {
180 pos = *wfullpath +
size - 1;
182 if (!extension_len && *pos ==
L'.') {
183 extension_len = path_len - 1;
185 if (path_len > max_short_name_size || extension_len > max_extension_size) {
192 if ((pos >= *wfullpath + 2) &&
193 (*wfullpath)[0] ==
L'\\' && (*wfullpath)[1] ==
L'\\') {
196 if (pos == *wfullpath + 2) {
200 if (!wmemchr(*wfullpath + 2,
L'\\', pos - *wfullpath - 2)) {
206 find_handle = FindFirstFileW(*wfullpath, &find_data);
207 if (find_handle != INVALID_HANDLE_VALUE) {
209 size_t file_len = wcslen(find_data.cFileName);
210 size_t oldsize =
size;
212 FindClose(find_handle);
213 size = trail_pos + file_len;
214 if (
size > (buffer_size ? buffer_size-1 : oldsize)) {
216 wcsncpy(
buf, *wfullpath, trail_pos);
221 wcsncpy(*wfullpath + trail_pos, find_data.cFileName, file_len + 1);
227user_length_in_path(
const wchar_t *wuser,
size_t len)
243 if (
len == -1)
len = lstrlenW(ws);
269 append_wstr(result, dir, -1,
278 size_t size = 0, whome_len = 0;
279 size_t buffer_len = 0;
280 long wpath_len = 0, wdir_len = 0;
281 wchar_t *wfullpath =
NULL, *wpath =
NULL, *wpath_pos =
NULL;
282 wchar_t *wdir =
NULL, *wdir_pos =
NULL;
283 wchar_t *whome =
NULL, *buffer =
NULL, *buffer_pos =
NULL;
287 wchar_t path_drive =
L'\0', dir_drive =
L'\0';
303 cp = path_cp = code_page(path_encoding);
316#if SIZEOF_INT < SIZEOF_LONG
317 if ((
long)(
int)path_len != path_len) {
328 if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] ==
L'~' &&
338 whome_len = wcslen(whome);
340 if (!IS_ABSOLUTE_PATH_P(whome, whome_len)) {
365 else if (wpath_len >= 2 && wpath_pos[1] ==
L':') {
372 path_drive = wpath_pos[0];
377 else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] ==
L'~') {
379 result = append_wstr(result, wpath_pos + 1, user_length_in_path(wpath_pos + 1, wpath_len - 1),
380 path_cp, path_encoding);
389 if (!ignore_dir && !
NIL_P(dir)) {
398#if SIZEOF_INT < SIZEOF_LONG
399 if ((
long)(
int)dir_len != dir_len) {
400 if (wpath)
free(wpath);
409 if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] ==
L'~' &&
420 whome_len = wcslen(whome);
422 if (!IS_ABSOLUTE_PATH_P(whome, whome_len)) {
439 else if (wdir_len >= 2 && wdir[1] ==
L':') {
451 while (pos < wdir_len && separators < 2) {
461 else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] ==
L'~') {
463 result = append_wstr(result, wdir_pos + 1, user_length_in_path(wdir_pos + 1, wdir_len - 1),
464 path_cp, path_encoding);
476 if (!ignore_dir && path_drive && dir_drive) {
477 if (towupper(path_drive) != towupper(dir_drive)) {
485 if (!ignore_dir && wpath_len >= 2 &&
IS_DIR_UNC_P(wpath)) {
497 buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1;
499 buffer = buffer_pos =
ALLOC_N(
wchar_t, (buffer_len + 1));
503 wcsncpy(buffer_pos, whome, whome_len);
504 buffer_pos += whome_len;
508 if (whome_len && wcsrchr(
L"\\/:", buffer_pos[-1]) ==
NULL) {
509 buffer_pos[0] =
L'\\';
512 else if (!dir_drive && path_drive) {
513 *buffer_pos++ = path_drive;
514 *buffer_pos++ =
L':';
522 wcsncpy(buffer_pos, wdir_pos, wdir_len);
523 buffer_pos += wdir_len;
527 if (wdir_len && wcsrchr(
L"\\/:", buffer_pos[-1]) ==
NULL) {
528 buffer_pos[0] =
L'\\';
534 wcsncpy(buffer_pos, wpath_pos, wpath_len);
535 buffer_pos += wpath_len;
539 if (wpath_len == 0) {
540 buffer_pos[0] =
L'.';
545 buffer_pos[0] =
L'\0';
548 if (!tainted && !IS_ABSOLUTE_PATH_P(buffer, buffer_len))
560 wfullpath = wfullpath_buffer;
565 wfullpath[
size - 2] !=
L':' &&
568 wfullpath[
size] =
L'\0';
572 if (wfullpath[
size - 1] ==
L'.') {
574 wfullpath[
size] =
L'\0';
578 size = remove_invalid_alternative_data(wfullpath,
size);
583 size = replace_to_long_name(&wfullpath,
size, bufsize);
587 replace_wchar(wfullpath,
L'\\',
L'/');
591 result = append_wstr(result, wfullpath,
size, path_cp, path_encoding);
610 if (wfullpath != wfullpath_buffer)
630 cp = path_cp = code_page(enc);
640 if (e == ERROR_MORE_DATA) {
654 path_cp = code_page(enc);
655 len = lstrlenW(wbuf);
670 if (!wpath)
return 0;
672 attr = GetFileAttributesW(wpath);
674 (attr & FILE_ATTRIBUTE_DIRECTORY)) {
678 HANDLE
h = CreateFileW(wpath, GENERIC_READ,
679 FILE_SHARE_READ | FILE_SHARE_WRITE,
680 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
681 if (
h != INVALID_HANDLE_VALUE) {
695 WCHAR *wname, wmode[4];
699 int e = 0,
n = MultiByteToWideChar(CP_ACP, 0, mode, -1,
NULL, 0);
701 MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode,
numberof(wmode));
704 len = MultiByteToWideChar(CP_UTF8, 0,
name,
n,
NULL, 0);
706 len = MultiByteToWideChar(CP_UTF8, 0,
name,
n, wname,
len);
709#if RUBY_MSVCRT_VERSION < 80 && !defined(HAVE__WFREOPEN_S)
710 e = _wfreopen(wname, wmode, file) ? 0 :
errno;
714 e = _wfreopen_s(&newfp, wname, wmode, file);
724 if (rb_code_page.count)
return;
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
rb_encoding * rb_filesystem_encoding(void)
int rb_utf8_encindex(void)
rb_encoding * rb_enc_get(VALUE obj)
int rb_ascii8bit_encindex(void)
int rb_enc_to_index(rb_encoding *enc)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
int rb_usascii_encindex(void)
rb_econv_t * rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags)
#define ECONV_UNDEF_REPLACE
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
#define ECONV_INVALID_REPLACE
int rb_enc_str_asciionly_p(VALUE)
void rb_econv_close(rb_econv_t *ec)
VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags)
char str[HTML_ESCAPE_MAX_LEN+1]
int rb_file_load_ok(const char *path)
VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)
VALUE rb_default_home_dir(VALUE result)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
VALUE rb_exc_new_str(VALUE, VALUE)
int rb_freopen(VALUE fname, const char *mode, FILE *file)
#define INVALID_CODE_PAGE
#define INVALID_FILE_ATTRIBUTES
#define IS_DIR_SEPARATOR_P(c)
void Init_w32_codepage(void)
VALUE rb_readlink(VALUE path, rb_encoding *resultenc)
#define fix_string_encoding(str, encoding)
void rb_enc_foreach_name(int(*func)(st_data_t name, st_data_t idx, st_data_t arg), st_data_t arg)
WCHAR * rb_w32_home_dir(void)
#define rb_w32_reparse_buffer_size(n)
int rb_w32_read_reparse_point(const WCHAR *path, rb_w32_reparse_buffer_t *rp, size_t bufsize, WCHAR **result, DWORD *len)
int rb_w32_map_errno(DWORD)