7 #ifndef INVALID_FILE_ATTRIBUTES
8 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
14 #define IS_DIR_SEPARATOR_P(c) (c == L'\\' || c == L'/')
15 #define IS_DIR_UNC_P(c) (IS_DIR_SEPARATOR_P(c[0]) && IS_DIR_SEPARATOR_P(c[1]))
18 #define INVALID_CODE_PAGE 51932
19 #define PATH_BUFFER_SIZE MAX_PATH * 2
21 #define insecure_obj_p(obj, level) ((level) >= 4 || ((level) > 0 && OBJ_TAINTED(obj)))
42 len = MultiByteToWideChar(code_page, 0,
RSTRING_PTR(str), -1,
NULL, 0) + 1;
43 *wstr = (
wchar_t *)
xmalloc(len *
sizeof(
wchar_t));
47 MultiByteToWideChar(code_page, 0,
RSTRING_PTR(str), -1, *wstr, len);
56 len = WideCharToMultiByte(code_page, 0, wstr, -1,
NULL, 0,
NULL,
NULL);
57 *str = (
char *)
xmalloc(len *
sizeof(
char));
58 WideCharToMultiByte(code_page, 0, wstr, -1, *str, len,
NULL,
NULL);
75 wchar_t *buffer =
NULL;
76 size_t buffer_len = 0, len = 0;
85 if (len = GetEnvironmentVariableW(L
"HOME",
NULL, 0)) {
89 else if (len = GetEnvironmentVariableW(L
"HOMEDRIVE",
NULL, 0)) {
91 if (len = GetEnvironmentVariableW(L
"HOMEPATH",
NULL, 0)) {
99 else if (len = GetEnvironmentVariableW(L
"USERPROFILE",
NULL, 0)) {
106 buffer = (
wchar_t *)
xmalloc(buffer_len *
sizeof(
wchar_t));
111 GetEnvironmentVariableW(L
"HOME", buffer, buffer_len);
115 len = GetEnvironmentVariableW(L
"HOMEDRIVE", buffer, buffer_len);
116 GetEnvironmentVariableW(L
"HOMEPATH", buffer + len, buffer_len - len);
120 GetEnvironmentVariableW(L
"USERPROFILE", buffer, buffer_len);
140 static const wchar_t prime[] = L
":$DATA";
141 enum { prime_len = (
sizeof(prime) /
sizeof(
wchar_t)) -1 };
143 if (size <= prime_len || _wcsnicmp(wfullpath + size - prime_len, prime, prime_len) != 0)
148 if (wfullpath[size - (prime_len + 1)] ==
':') {
150 size -= prime_len + 1;
151 wfullpath[
size] = L
'\0';
155 wchar_t *pos = wfullpath + size - (prime_len + 1);
159 wfullpath[
size] = L
'\0';
172 return AreFileApisANSI() ? CP_ACP : CP_OEMCP;
183 VALUE code_page_value, name_key;
200 name_key = (
VALUE)&fake_str;
204 if (code_page_value !=
Qnil)
205 return (UINT)
FIX2INT(code_page_value);
210 if (!
NIL_P(encoding)) {
222 if (names_ary !=
Qundef) {
227 if (code_page != 0) {
257 WIN32_FIND_DATAW find_data;
269 size_t const max_short_name_size = 8 + 1 + 3;
270 size_t const max_extension_size = 3;
271 size_t path_len = 1, extension_len = 0;
272 wchar_t *pos = *wfullpath;
274 if (size == 3 && pos[1] == L
':' && pos[2] == L
'\\' && pos[3] == L
'\0') {
280 if (wcspbrk(pos, L
"*?")) {
284 pos = *wfullpath + size - 1;
286 if (!extension_len && *pos == L
'.') {
287 extension_len = path_len - 1;
289 if (path_len > max_short_name_size || extension_len > max_extension_size) {
296 find_handle = FindFirstFileW(*wfullpath, &find_data);
297 if (find_handle != INVALID_HANDLE_VALUE) {
298 size_t trail_pos = wcslen(*wfullpath);
299 size_t file_len = wcslen(find_data.cFileName);
301 FindClose(find_handle);
302 while (trail_pos > 0) {
307 size = trail_pos + 1 + file_len;
308 if ((size + 1) >
sizeof(*wfullpath) /
sizeof((*wfullpath)[0])) {
309 wchar_t *
buf = (
wchar_t *)
xmalloc((size + 1) *
sizeof(wchar_t));
310 wcsncpy(buf, *wfullpath, trail_pos + 1);
315 wcsncpy(*wfullpath + trail_pos + 1, find_data.cFileName, file_len + 1);
324 wchar_t *wuser = *wpath + offset;
325 wchar_t *pos = wuser;
354 size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0;
355 size_t buffer_len = 0;
356 char *fullpath =
NULL;
357 wchar_t *wfullpath =
NULL, *wpath =
NULL, *wpath_pos =
NULL;
358 wchar_t *wdir =
NULL, *wdir_pos =
NULL;
359 wchar_t *whome =
NULL, *buffer =
NULL, *buffer_pos =
NULL;
361 VALUE path = fname, dir = dname;
363 wchar_t path_drive = L
'\0', dir_drive = L
'\0';
394 if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L
'~' &&
404 whome_len = wcslen(whome);
406 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
429 else if (wpath_len >= 2 && wpath_pos[1] == L
':') {
436 path_drive = wpath_pos[0];
439 else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L
'~') {
449 if (!ignore_dir && !
NIL_P(dir)) {
458 if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L
'~' &&
469 whome_len = wcslen(whome);
471 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
488 else if (wdir_len >= 2 && wdir[1] == L
':') {
498 size_t separators = 0;
500 while (pos < wdir_len && separators < 2) {
510 else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] == L
'~') {
523 if (!ignore_dir && path_drive && dir_drive) {
524 if (towupper(path_drive) == towupper(dir_drive)) {
536 if (!ignore_dir && wpath_len >= 2 &&
IS_DIR_UNC_P(wpath)) {
548 buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1;
550 buffer = buffer_pos = (
wchar_t *)
xmalloc((buffer_len + 1) *
sizeof(wchar_t));
554 wcsncpy(buffer_pos, whome, whome_len);
555 buffer_pos += whome_len;
559 if (whome_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
560 buffer_pos[0] = L
'\\';
569 wcsncpy(buffer_pos, wdir_pos, wdir_len);
570 buffer_pos += wdir_len;
574 if (wdir_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
575 buffer_pos[0] = L
'\\';
581 wcsncpy(buffer_pos, wpath_pos, wpath_len);
582 buffer_pos += wpath_len;
586 if (wpath_len == 0) {
587 buffer_pos[0] = L
'.';
592 buffer_pos[0] = L
'\0';
595 if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 &&
IS_DIR_UNC_P(buffer)))
603 wfullpath = (
wchar_t *)
xmalloc(size *
sizeof(
wchar_t));
604 size = GetFullPathNameW(buffer, size, wfullpath,
NULL);
607 wfullpath = wfullpath_buffer;
612 wfullpath[size - 2] != L
':' &&
615 wfullpath[
size] = L
'\0';
619 if (wfullpath[size - 1] == L
'.') {
621 wfullpath[
size] = L
'\0';
635 size = WideCharToMultiByte(cp, 0, wfullpath, size,
NULL, 0,
NULL,
NULL);
678 if (wfullpath && wfullpath != wfullpath_buffer)
691 DWORD attr = GetFileAttributes(path);
693 attr & FILE_ATTRIBUTE_DIRECTORY) {
697 HANDLE h = CreateFile(path, GENERIC_READ,
698 FILE_SHARE_READ | FILE_SHARE_WRITE,
699 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
700 if (h != INVALID_HANDLE_VALUE) {
RUBY_EXTERN VALUE rb_cString
void rb_w32_init_file(void)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
size_t strlen(const char *)
#define ENCODING_CODERANGE_SET(obj, encindex, cr)
static UINT system_code_page(void)
#define ENC_CODERANGE_CLEAR(obj)
VALUE rb_enc_from_encoding(rb_encoding *encoding)
int rb_usascii_encindex(void)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
struct RString::@73::@74 heap
void rb_str_set_len(VALUE, long)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
#define IS_DIR_SEPARATOR_P(c)
rb_encoding * rb_utf8_encoding(void)
#define ENC_CODERANGE_7BIT
static void convert_wchar_to_mb(const wchar_t *wstr, char **str, size_t *str_len, UINT code_page)
static void convert_mb_to_wchar(VALUE str, wchar_t **wstr, wchar_t **wstr_pos, size_t *wstr_len, UINT code_page)
static UINT code_page(rb_encoding *enc)
static size_t remove_invalid_alternative_data(wchar_t *wfullpath, size_t size)
static VALUE enc_name(VALUE self)
void rb_gc_register_mark_object(VALUE obj)
VALUE rb_str_resize(VALUE, long)
static wchar_t * home_dir(void)
unsigned char buf[MIME_BUF_SIZE]
rb_encoding * rb_usascii_encoding(void)
static VALUE fix_string_encoding(VALUE str, rb_encoding *encoding)
void rb_str_modify(VALUE)
VALUE rb_usascii_str_new2(const char *)
rb_encoding * rb_enc_get(VALUE obj)
static size_t replace_to_long_name(wchar_t **wfullpath, size_t size, int heap)
static VALUE get_user_from_path(wchar_t **wpath, int offset, UINT cp, UINT path_cp, rb_encoding *path_encoding)
rb_encoding * rb_filesystem_encoding(void)
static VALUE rb_code_page
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
int rb_file_load_ok(const char *path)
#define StringValuePtr(v)
rb_encoding * rb_ascii8bit_encoding(void)
#define INVALID_CODE_PAGE
#define CONST_ID(var, str)
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
#define INVALID_FILE_ATTRIBUTES
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
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)