static VALUE rb_f_load(int argc, VALUE *argv) { VALUE fname, wrap, path, orig_fname; rb_scan_args(argc, argv, "11", &fname, &wrap); if (RUBY_DTRACE_LOAD_ENTRY_ENABLED()) { RUBY_DTRACE_LOAD_ENTRY(StringValuePtr(fname), rb_sourcefile(), rb_sourceline()); } orig_fname = FilePathValue(fname); fname = rb_str_encode_ospath(orig_fname); path = rb_find_file(fname); if (!path) { if (!rb_file_load_ok(RSTRING_PTR(fname))) load_failed(orig_fname); path = fname; } rb_load_internal(path, RTEST(wrap)); if (RUBY_DTRACE_LOAD_RETURN_ENABLED()) { RUBY_DTRACE_LOAD_RETURN(StringValuePtr(fname), rb_sourcefile(), rb_sourceline()); } return Qtrue; }
// Win32::Symlink::readlink(file) static VALUE rb_readlink(VALUE mod, VALUE file) { (void)mod; FilePathValue(file); file = rb_str_encode_ospath(file); return win32_readlink(RSTRING_PTR(file)); }
// Win32::Symlink::symlink(file, symlink) static VALUE rb_symlink(VALUE mod, VALUE target, VALUE symlink) { (void)mod; VALUE error = Qnil; wchar_t* wtarget = NULL; wchar_t* wsymlink = NULL; BOOL res; DWORD flags = 0; target = FilePathValue(target); symlink = FilePathValue(symlink); target = rb_str_encode_ospath(target); symlink = rb_str_encode_ospath(symlink); wtarget = filecp_to_wstr(RSTRING_PTR(target), NULL); wsymlink = filecp_to_wstr(RSTRING_PTR(symlink), NULL); if( is_directory(wtarget) ) { flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; } res = create_symbolic_linkW(wsymlink, wtarget, flags); if( !res ) { error = make_api_error(RSTRING_PTR(target)); } xfree(wtarget); xfree(wsymlink); if( !NIL_P(error) ) { rb_exc_raise(error); } return INT2FIX(0); }
// Win32::Symlink::symlink?(file) static VALUE rb_symlink_p(VALUE mod, VALUE file) { (void)mod; DWORD attrs; FilePathValue(file); file = rb_str_encode_ospath(file); attrs = GetFileAttributes(RSTRING_PTR(file)); if( attrs == INVALID_FILE_ATTRIBUTES ) { rb_exc_raise(make_api_error(RSTRING_PTR(file))); } return (attrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0; }
static VALUE rb_f_load(int argc, VALUE *argv) { VALUE fname, wrap, path, orig_fname; rb_scan_args(argc, argv, "11", &fname, &wrap); orig_fname = rb_get_path_check_to_string(fname, rb_safe_level()); fname = rb_str_encode_ospath(orig_fname); RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname)); path = rb_find_file(fname); if (!path) { if (!rb_file_load_ok(RSTRING_PTR(fname))) load_failed(orig_fname); path = fname; } rb_load_internal(path, RTEST(wrap)); RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname)); return Qtrue; }
VALUE rb_resolve_feature_path(VALUE klass, VALUE fname) { VALUE path; int found; VALUE sym; fname = rb_get_path_check(fname, 0); path = rb_str_encode_ospath(fname); found = search_required(path, &path, 0, no_feature_p); switch (found) { case 'r': sym = ID2SYM(rb_intern("rb")); break; case 's': sym = ID2SYM(rb_intern("so")); break; default: load_failed(fname); } return rb_ary_new_from_args(2, sym, path); }
static VALUE combined_watch(BOOL recursively, int argc, VALUE *argv, VALUE self) { WDM_PMonitor monitor; WDM_PEntry entry; int directory_letters_count; VALUE directory, flags, os_encoded_directory; BOOL running; // TODO: Maybe raise a more user-friendly error? rb_need_block(); Data_Get_Struct(self, WDM_Monitor, monitor); EnterCriticalSection(&monitor->lock); running = monitor->running; LeaveCriticalSection(&monitor->lock); if ( running ) { rb_raise(eWDM_MonitorRunningError, "You can't watch new directories while the monitor is running!"); } rb_scan_args(argc, argv, "1*", &directory, &flags); Check_Type(directory, T_STRING); entry = wdm_entry_new(); entry->user_data->watch_childeren = recursively; entry->user_data->callback = rb_block_proc(); entry->user_data->flags = RARRAY_LEN(flags) == 0 ? WDM_MONITOR_FLAGS_DEFAULT : extract_flags_from_rb_array(flags); // WTF Ruby source: The original code (file.c) uses the following macro to make sure that the encoding // of the string is ASCII-compatible, but UTF-16LE (Windows default encoding) is not!!! // // FilePathValue(directory); os_encoded_directory = rb_str_encode_ospath(directory); // RSTRING_LEN can't be used because it would return the count of bytes the string uses in its encoding (like UTF-8). // UTF-8 might use more than one byte for the char, which is not needed for WCHAR strings. // Also, the result of MultiByteToWideChar _includes_ the NULL char at the end, which is not true for RSTRING. // // Example: 'C:\Users\Maher\Desktop\تجربة' with __ENCODING__ == UTF-8 // MultiByteToWideChar => 29 (28-char + null) // RSTRING_LEN => 33 (23-char + 10-bytes for 5 Arabic letters which take 2 bytes each) // directory_letters_count = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(os_encoded_directory), -1, NULL, 0); entry->user_data->dir = ALLOCA_N(WCHAR, directory_letters_count); MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(os_encoded_directory), -1, entry->user_data->dir, directory_letters_count); WDM_WDEBUG("New path to watch: '%s'", entry->user_data->dir); entry->user_data->dir = wdm_utils_full_pathname(entry->user_data->dir); if ( entry->user_data->dir == 0 ) { wdm_entry_free(entry); rb_raise(eWDM_Error, "Can't get the absolute path for the passed directory: '%s'!", RSTRING_PTR(directory)); } if ( ! wdm_utils_unicode_is_directory(entry->user_data->dir) ) { wdm_entry_free(entry); rb_raise(eWDM_InvalidDirectoryError, "No such directory: '%s'!", RSTRING_PTR(directory)); } entry->dir_handle = CreateFileW( entry->user_data->dir, // pointer to the file name FILE_LIST_DIRECTORY, // access (read/write) mode FILE_SHARE_READ // share mode | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, // security descriptor OPEN_EXISTING, // how to create FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // file attributes NULL ); if ( entry->dir_handle == INVALID_HANDLE_VALUE ) { wdm_entry_free(entry); rb_raise(eWDM_Error, "Can't watch directory: '%s'!", RSTRING_PTR(directory)); } // Store a reference to the entry instead of an event as the event // won't be used when using callbacks. entry->event_container.hEvent = wdm_monitor_callback_param_new(monitor, entry); wdm_monitor_update_head(monitor, entry); WDM_WDEBUG("Watching directory: '%s'", entry->user_data->dir); return Qnil; }
/* * returns * 0: if already loaded (false) * 1: successfully loaded (true) * <0: not found (LoadError) * >1: exception */ int rb_require_internal(VALUE fname, int safe) { volatile int result = -1; rb_thread_t *th = GET_THREAD(); volatile VALUE errinfo = th->errinfo; int state; struct { int safe; } volatile saved; char *volatile ftptr = 0; if (RUBY_DTRACE_REQUIRE_ENTRY_ENABLED()) { RUBY_DTRACE_REQUIRE_ENTRY(StringValuePtr(fname), rb_sourcefile(), rb_sourceline()); } TH_PUSH_TAG(th); saved.safe = rb_safe_level(); if ((state = EXEC_TAG()) == 0) { VALUE path; long handle; int found; rb_set_safe_level_force(safe); FilePathValue(fname); rb_set_safe_level_force(0); if (RUBY_DTRACE_FIND_REQUIRE_ENTRY_ENABLED()) { RUBY_DTRACE_FIND_REQUIRE_ENTRY(StringValuePtr(fname), rb_sourcefile(), rb_sourceline()); } path = rb_str_encode_ospath(fname); found = search_required(path, &path, safe); if (RUBY_DTRACE_FIND_REQUIRE_RETURN_ENABLED()) { RUBY_DTRACE_FIND_REQUIRE_RETURN(StringValuePtr(fname), rb_sourcefile(), rb_sourceline()); } if (found) { if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) { result = 0; } else if (!*ftptr) { rb_provide_feature(path); result = TAG_RETURN; } else { switch (found) { case 'r': rb_load_internal(path, 0); break; case 's': handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext, path, 0, path); rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); break; } rb_provide_feature(path); result = TAG_RETURN; } } } TH_POP_TAG(); load_unlock(ftptr, !state); rb_set_safe_level_force(saved.safe); if (state) { /* never TAG_RETURN */ return state; } th->errinfo = errinfo; if (RUBY_DTRACE_REQUIRE_RETURN_ENABLED()) { RUBY_DTRACE_REQUIRE_RETURN(StringValuePtr(fname), rb_sourcefile(), rb_sourceline()); } return result; }
/* * returns * 0: if already loaded (false) * 1: successfully loaded (true) * <0: not found (LoadError) * >1: exception */ int rb_require_internal(VALUE fname, int safe) { volatile int result = -1; rb_execution_context_t *ec = GET_EC(); volatile VALUE errinfo = ec->errinfo; enum ruby_tag_type state; struct { int safe; } volatile saved; char *volatile ftptr = 0; VALUE path; fname = rb_get_path_check(fname, safe); path = rb_str_encode_ospath(fname); RUBY_DTRACE_HOOK(REQUIRE_ENTRY, RSTRING_PTR(fname)); EC_PUSH_TAG(ec); saved.safe = rb_safe_level(); if ((state = EC_EXEC_TAG()) == TAG_NONE) { long handle; int found; rb_set_safe_level_force(0); RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname)); found = search_required(path, &path, safe, rb_feature_p); RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN, RSTRING_PTR(fname)); if (found) { if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) { result = 0; } else if (!*ftptr) { rb_provide_feature(path); result = TAG_RETURN; } else { switch (found) { case 'r': state = rb_load_internal0(ec, path, 0); break; case 's': handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext, path, VM_BLOCK_HANDLER_NONE, path); rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); break; } if (!state) { rb_provide_feature(path); result = TAG_RETURN; } } } } EC_POP_TAG(); load_unlock(ftptr, !state); rb_set_safe_level_force(saved.safe); if (state) { RB_GC_GUARD(fname); /* never TAG_RETURN */ return state; } ec->errinfo = errinfo; RUBY_DTRACE_HOOK(REQUIRE_RETURN, RSTRING_PTR(fname)); return result; }