Beispiel #1
0
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;
}
Beispiel #5
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;
}
Beispiel #6
0
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);
}
Beispiel #7
0
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;
}
Beispiel #8
0
/*
 * 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;
}
Beispiel #9
0
/*
 * 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;
}