1 #if defined(__MINGW32__) 3 # define MINGW_HAS_SECURE_API 1 13 #ifndef INVALID_FILE_ATTRIBUTES 14 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 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])) 27 #define INVALID_CODE_PAGE 51932 28 #define PATH_BUFFER_SIZE MAX_PATH * 2 30 #define insecure_obj_p(obj, level) ((level) > 0 && OBJ_TAINTED(obj)) 33 #define system_code_page rb_w32_filecp 34 #define mbstr_to_wstr rb_w32_mbstr_to_wstr 35 #define wstr_to_mbstr rb_w32_wstr_to_mbstr 51 static const wchar_t prime[] =
L":$DATA";
52 enum { prime_len = (
sizeof(prime) /
sizeof(
wchar_t)) -1 };
54 if (size <= prime_len || _wcsnicmp(wfullpath + size - prime_len, prime, prime_len) != 0)
59 if (wfullpath[size - (prime_len + 1)] ==
':') {
61 size -= prime_len + 1;
62 wfullpath[
size] =
L'\0';
66 wchar_t *pos = wfullpath + size - (prime_len + 1);
70 wfullpath[
size] =
L'\0';
84 const char *n = (
const char *)name;
85 if (strncmp(
"CP", n, 2) == 0) {
92 unsigned int i =
count;
93 count = (((idx + 4) & ~31) | 28);
94 table =
realloc(table, count *
sizeof(*table));
100 table[idx] = (USHORT)code_page;
135 #define fix_string_encoding(str, encoding) rb_str_conv_enc((str), (encoding), rb_utf8_encoding()) 144 WIN32_FIND_DATAW find_data;
156 size_t const max_short_name_size = 8 + 1 + 3;
157 size_t const max_extension_size = 3;
158 size_t path_len = 1, extension_len = 0;
159 wchar_t *pos = *wfullpath;
161 if (size == 3 && pos[1] ==
L':' && pos[2] ==
L'\\' && pos[3] ==
L'\0') {
167 if (wcspbrk(pos,
L"*?")) {
171 pos = *wfullpath + size - 1;
173 if (!extension_len && *pos ==
L'.') {
174 extension_len = path_len - 1;
176 if (path_len > max_short_name_size || extension_len > max_extension_size) {
183 find_handle = FindFirstFileW(*wfullpath, &find_data);
184 if (find_handle != INVALID_HANDLE_VALUE) {
186 size_t file_len = wcslen(find_data.cFileName);
187 size_t oldsize =
size;
189 FindClose(find_handle);
190 size = trail_pos + file_len;
191 if (size > (buffer_size ? buffer_size-1 : oldsize)) {
193 wcsncpy(buf, *wfullpath, trail_pos);
198 wcsncpy(*wfullpath + trail_pos, find_data.cFileName, file_len + 1);
217 long olen, nlen = (long)len;
220 if (len == -1) len = lstrlenW(ws);
221 nlen = WideCharToMultiByte(cp, 0, ws, len,
NULL, 0,
NULL,
NULL);
255 size_t size = 0, whome_len = 0;
256 size_t buffer_len = 0;
257 long wpath_len = 0, wdir_len = 0;
258 char *fullpath =
NULL;
259 wchar_t *wfullpath =
NULL, *wpath =
NULL, *wpath_pos =
NULL;
260 wchar_t *wdir =
NULL, *wdir_pos =
NULL;
261 wchar_t *whome =
NULL, *buffer =
NULL, *buffer_pos =
NULL;
263 VALUE path = fname, dir = dname;
294 #if SIZEOF_INT < SIZEOF_LONG 295 if ((
long)(
int)path_len != path_len) {
306 if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] ==
L'~' &&
316 whome_len = wcslen(whome);
318 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
343 else if (wpath_len >= 2 && wpath_pos[1] ==
L':') {
350 path_drive = wpath_pos[0];
355 else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] ==
L'~') {
358 path_cp, path_encoding);
367 if (!ignore_dir && !
NIL_P(dir)) {
376 #if SIZEOF_INT < SIZEOF_LONG 377 if ((
long)(
int)dir_len != dir_len) {
378 if (wpath)
free(wpath);
387 if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] ==
L'~' &&
398 whome_len = wcslen(whome);
400 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
417 else if (wdir_len >= 2 && wdir[1] ==
L':') {
429 while (pos < wdir_len && separators < 2) {
439 else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] ==
L'~') {
442 path_cp, path_encoding);
454 if (!ignore_dir && path_drive && dir_drive) {
455 if (towupper(path_drive) != towupper(dir_drive)) {
463 if (!ignore_dir && wpath_len >= 2 &&
IS_DIR_UNC_P(wpath)) {
475 buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1;
477 buffer = buffer_pos =
ALLOC_N(
wchar_t, (buffer_len + 1));
481 wcsncpy(buffer_pos, whome, whome_len);
482 buffer_pos += whome_len;
486 if (whome_len && wcsrchr(
L"\\/:", buffer_pos[-1]) ==
NULL) {
487 buffer_pos[0] =
L'\\';
490 else if (!dir_drive && path_drive) {
492 *buffer_pos++ =
L':';
500 wcsncpy(buffer_pos, wdir_pos, wdir_len);
501 buffer_pos += wdir_len;
505 if (wdir_len && wcsrchr(
L"\\/:", buffer_pos[-1]) ==
NULL) {
506 buffer_pos[0] =
L'\\';
512 wcsncpy(buffer_pos, wpath_pos, wpath_len);
513 buffer_pos += wpath_len;
517 if (wpath_len == 0) {
518 buffer_pos[0] =
L'.';
523 buffer_pos[0] =
L'\0';
526 if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 &&
IS_DIR_UNC_P(buffer)))
534 wfullpath =
ALLOC_N(
wchar_t, size);
535 size = GetFullPathNameW(buffer, size, wfullpath,
NULL);
538 wfullpath = wfullpath_buffer;
543 wfullpath[size - 2] !=
L':' &&
546 wfullpath[
size] =
L'\0';
550 if (wfullpath[size - 1] ==
L'.') {
552 wfullpath[
size] =
L'\0';
569 result =
append_wstr(result, wfullpath, size, path_cp, path_encoding);
588 if (wfullpath != wfullpath_buffer)
602 VALUE wtmp = 0, wpathbuf, str;
617 wpath =
ALLOCV_N(WCHAR, wpathbuf, len+1);
621 if (e == ERROR_MORE_DATA) {
636 len = lstrlenW(wbuf);
651 if (!wpath)
return 0;
653 attr = GetFileAttributesW(wpath);
655 (attr & FILE_ATTRIBUTE_DIRECTORY)) {
659 HANDLE h = CreateFileW(wpath, GENERIC_READ,
660 FILE_SHARE_READ | FILE_SHARE_WRITE,
661 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
662 if (h != INVALID_HANDLE_VALUE) {
676 WCHAR *wname, wmode[4];
680 int e = 0, n = MultiByteToWideChar(CP_ACP, 0, mode, -1,
NULL, 0);
681 if (n >
numberof(wmode))
return EINVAL;
682 MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode,
numberof(wmode));
685 len = MultiByteToWideChar(CP_UTF8, 0, name, n,
NULL, 0);
686 wname =
ALLOCV_N(WCHAR, wtmp, len + 1);
687 len = MultiByteToWideChar(CP_UTF8, 0, name, n, wname, len);
690 #if RUBY_MSVCRT_VERSION < 80 && !defined(HAVE__WFREOPEN_S) 691 e = _wfreopen(wname, wmode, file) ? 0 :
errno;
695 e = _wfreopen_s(&newfp, wname, wmode, file);
static int code_page_i(st_data_t name, st_data_t idx, st_data_t arg)
static VALUE append_wstr(VALUE dst, const WCHAR *ws, ssize_t len, UINT cp, rb_encoding *enc)
static size_t replace_to_long_name(wchar_t **wfullpath, size_t size, size_t buffer_size)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
rb_econv_t * rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags)
VALUE rb_exc_new_str(VALUE etype, VALUE str)
int rb_w32_read_reparse_point(const WCHAR *path, rb_w32_reparse_buffer_t *rp, size_t bufsize, WCHAR **result, DWORD *len)
void rb_econv_close(rb_econv_t *ec)
SSL_METHOD *(* func)(void)
int rb_usascii_encindex(void)
void rb_str_set_len(VALUE, long)
void rb_raise(VALUE exc, const char *fmt,...)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
VALUE rb_readlink(VALUE path, rb_encoding *resultenc)
#define IS_DIR_SEPARATOR_P(c)
void Init_w32_codepage(void)
int rb_w32_map_errno(DWORD)
WCHAR * rb_w32_home_dir(void)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
void rb_exc_raise(VALUE mesg)
int rb_enc_to_index(rb_encoding *enc)
static UINT code_page(rb_encoding *enc)
static size_t remove_invalid_alternative_data(wchar_t *wfullpath, size_t size)
#define ECONV_INVALID_REPLACE
int rb_ascii8bit_encindex(void)
void rb_enc_foreach_name(int(*func)(st_data_t name, st_data_t idx, st_data_t arg), st_data_t arg)
#define ALLOCV_N(type, v, n)
#define fix_string_encoding(str, encoding)
void rb_str_modify_expand(VALUE, long)
unsigned char buf[MIME_BUF_SIZE]
static size_t user_length_in_path(const wchar_t *wuser, size_t len)
int rb_utf8_encindex(void)
VALUE rb_str_new_cstr(const char *)
#define rb_w32_reparse_buffer_size(n)
register unsigned int len
#define ECONV_UNDEF_REPLACE
rb_encoding * rb_enc_get(VALUE obj)
int rb_freopen(VALUE fname, const char *mode, FILE *file)
static struct code_page_table rb_code_page
VALUE rb_default_home_dir(VALUE result)
rb_encoding * rb_filesystem_encoding(void)
static int path_drive(const WCHAR *path)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
int rb_file_load_ok(const char *path)
#define INVALID_CODE_PAGE
#define rb_syserr_fail_path(err, path)
VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags)
int rb_enc_str_asciionly_p(VALUE)
#define INVALID_FILE_ATTRIBUTES
static void replace_wchar(wchar_t *s, int find, int replace)
VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)