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);
323 size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0;
324 size_t buffer_len = 0;
325 char *fullpath =
NULL;
327 wchar_t *whome =
NULL, *buffer =
NULL, *buffer_pos =
NULL;
329 VALUE path = fname, dir = dname;
331 wchar_t path_drive = L
'\0', dir_drive = L
'\0';
362 if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L
'~' &&
372 whome_len = wcslen(whome);
374 if (PathIsRelativeW(whome) && !(whome_len >= 2 &&
IS_DIR_UNC_P(whome))) {
396 else if (wpath_len >= 2 && wpath_pos[1] == L
':') {
403 path_drive = wpath_pos[0];
406 else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L
'~') {
407 wchar_t *wuser = wpath_pos + 1;
408 wchar_t *pos = wuser;
438 if (!ignore_dir && !
NIL_P(dir)) {
447 if (wdir_len >= 2 && wdir[1] == L
':') {
457 size_t separators = 0;
459 while (pos < wdir_len && separators < 2) {
472 if (!ignore_dir && path_drive && dir_drive) {
473 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 = (
wchar_t *)
xmalloc((buffer_len + 1) *
sizeof(wchar_t));
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
'\\';
518 wcsncpy(buffer_pos, wdir, wdir_len);
519 buffer_pos += wdir_len;
523 if (wdir_len && wcsrchr(L
"\\/:", buffer_pos[-1]) ==
NULL) {
524 buffer_pos[0] = L
'\\';
530 wcsncpy(buffer_pos, wpath_pos, wpath_len);
531 buffer_pos += wpath_len;
535 if (wpath_len == 0) {
536 buffer_pos[0] = L
'.';
541 buffer_pos[0] = L
'\0';
544 if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 &&
IS_DIR_UNC_P(buffer)))
552 wfullpath = (
wchar_t *)
xmalloc(size *
sizeof(
wchar_t));
553 size = GetFullPathNameW(buffer, size, wfullpath,
NULL);
556 wfullpath = wfullpath_buffer;
561 wfullpath[size - 2] != L
':' &&
564 wfullpath[
size] = L
'\0';
568 if (wfullpath[size - 1] == L
'.') {
570 wfullpath[
size] = L
'\0';
584 size = WideCharToMultiByte(cp, 0, wfullpath, size,
NULL, 0,
NULL,
NULL);
627 if (wfullpath && wfullpath != wfullpath_buffer)
640 DWORD attr = GetFileAttributes(path);
642 attr & FILE_ATTRIBUTE_DIRECTORY) {
646 HANDLE h = CreateFile(path, GENERIC_READ,
647 FILE_SHARE_READ | FILE_SHARE_WRITE,
648 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
649 if (h != INVALID_HANDLE_VALUE) {