1 #if defined(__MINGW32__) 3 # define MINGW_HAS_SECURE_API 1 13 #ifndef INVALID_FILE_ATTRIBUTES 14 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 18 static 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])) 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 38 replace_wchar(
wchar_t *s,
int find,
int replace)
49 remove_invalid_alternative_data(
wchar_t *wfullpath,
size_t size)
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) {
86 int code_page = atoi(n + 2);
88 struct code_page_table *cp = (
struct code_page_table *)arg;
89 unsigned int count = cp->count;
90 USHORT *table = cp->table;
92 unsigned int i =
count;
93 count = (((idx + 4) & ~31) | 28);
94 table =
realloc(table, count *
sizeof(*table));
100 table[idx] = (USHORT)code_page;
129 if (0 <= enc_idx && (
unsigned int)enc_idx < rb_code_page.count)
130 return rb_code_page.table[enc_idx];
135 #define fix_string_encoding(str, encoding) rb_str_conv_enc((str), (encoding), rb_utf8_encoding()) 142 replace_to_long_name(
wchar_t **wfullpath,
size_t size,
size_t buffer_size)
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);
204 user_length_in_path(
const wchar_t *wuser,
size_t len)
217 long olen, nlen = (long)
len;
220 if (
len == -1)
len = lstrlenW(ws);
246 append_wstr(result, dir, -1,
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;
265 wchar_t path_drive = L
'\0', dir_drive = L
'\0';
281 cp = path_cp = code_page(path_encoding);
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
'~') {
357 result = append_wstr(result, wpath_pos + 1, user_length_in_path(wpath_pos + 1, wpath_len - 1),
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
'~') {
441 result = append_wstr(result, wdir_pos + 1, user_length_in_path(wdir_pos + 1, wdir_len - 1),
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) {
491 *buffer_pos++ = 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';
556 size = remove_invalid_alternative_data(wfullpath, size);
561 size = replace_to_long_name(&wfullpath, size, bufsize);
565 replace_wchar(wfullpath, L
'\\', L
'/');
569 result = append_wstr(result, wfullpath, size, path_cp, path_encoding);
588 if (wfullpath != wfullpath_buffer)
602 VALUE wtmp = 0, wpathbuf, str;
611 cp = path_cp = code_page(enc);
617 wpath =
ALLOCV_N(WCHAR, wpathbuf, len+1);
621 if (e == ERROR_MORE_DATA) {
635 path_cp = code_page(enc);
636 len = lstrlenW(wbuf);
637 str = append_wstr(
rb_enc_str_new(0, 0, enc), wbuf, len, path_cp, enc);
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);
705 if (rb_code_page.count)
return;
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)
void rb_raise(VALUE exc, const char *fmt,...)
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)
int rb_usascii_encindex(void)
void rb_str_set_len(VALUE, long)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
VALUE rb_exc_new_str(VALUE etype, VALUE str)
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
int rb_enc_to_index(rb_encoding *enc)
#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]
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
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)
VALUE rb_default_home_dir(VALUE result)
rb_encoding * rb_filesystem_encoding(void)
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
VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)