VALUE rb_require_safe(VALUE fname, int safe) { volatile VALUE result = Qnil; rb_thread_t *th = GET_THREAD(); volatile VALUE errinfo = th->errinfo; int state; struct { int safe; } volatile saved; char *volatile ftptr = 0; PUSH_TAG(); 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); found = search_required(fname, &path, safe); if (found) { if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) { result = Qfalse; } 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 = Qtrue; } } } POP_TAG(); load_unlock(ftptr, !state); rb_set_safe_level_force(saved.safe); if (state) { JUMP_TAG(state); } if (NIL_P(result)) { load_failed(fname); } th->errinfo = errinfo; return result; }
void rb_load(VALUE fname, int wrap) { VALUE tmp = rb_find_file(FilePathValue(fname)); if (!tmp) load_failed(fname); rb_load_internal(tmp, wrap); }
static VALUE file_to_load(VALUE fname) { VALUE tmp = rb_find_file(FilePathValue(fname)); if (!tmp) load_failed(fname); return tmp; }
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; }
VALUE rb_readlink(VALUE path) { ssize_t len; WCHAR *wpath, wbuf[MAX_PATH]; rb_encoding *enc; UINT cp, path_cp; FilePathValue(path); enc = rb_enc_get(path); cp = path_cp = code_page(enc); if (cp == INVALID_CODE_PAGE) { path = fix_string_encoding(path, enc); cp = CP_UTF8; } wpath = mbstr_to_wstr(cp, RSTRING_PTR(path), RSTRING_LEN(path)+rb_enc_mbminlen(enc), NULL); if (!wpath) rb_memerror(); len = rb_w32_wreadlink(wpath, wbuf, numberof(wbuf)); free(wpath); if (len < 0) rb_sys_fail_path(path); enc = rb_filesystem_encoding(); cp = path_cp = code_page(enc); if (cp == INVALID_CODE_PAGE) cp = CP_UTF8; return append_wstr(rb_enc_str_new(0, 0, enc), wbuf, len, cp, path_cp, enc); }
// 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)); }
static VALUE rb_mod_autoload(VALUE mod, VALUE sym, VALUE file) { ID id = rb_to_id(sym); FilePathValue(file); rb_autoload_str(mod, id, file); return Qnil; }
static VALUE rb_mod_autoload(VALUE mod, VALUE sym, VALUE file) { ID id = rb_to_id(sym); FilePathValue(file); rb_autoload(mod, id, RSTRING_PTR(file)); return Qnil; }
static void check_dirname(volatile VALUE *dir) { char *path, *pend; rb_secure(2); FilePathValue(*dir); path = RSTRING_PTR(*dir); if (path && *(pend = rb_path_end(rb_path_skip_prefix(path)))) { *dir = rb_str_new(path, pend - path); } }
VALUE rb_require_safe(VALUE fname, int safe) { FilePathValue(fname); // Immediately, check out if we have an AOT feature for this. if (rb_vm_aot_feature_load(RSTRING_PTR(fname))) { rb_provide_feature(fname); return Qtrue; } #if MACRUBY_STATIC rb_raise(rb_eRuntimeError, "#require is not supported in MacRuby static"); #else VALUE result = Qnil; VALUE path; int type = 0; if (search_required(fname, &path, &type)) { if (path == 0) { result = Qfalse; } else { rb_set_safe_level_force(0); rb_provide_feature(path); switch (type) { case TYPE_RB: rb_rescue2(load_try, path, load_rescue, path, rb_eException, 0); break; case TYPE_RBO: dln_load(RSTRING_PTR(path), false); break; case TYPE_BUNDLE: dln_load(RSTRING_PTR(path), true); break; default: abort(); } result = Qtrue; } } if (NIL_P(result)) { load_failed(fname); } return result; #endif }
/* * call-seq: * DBM.new(filename[, mode[, flags]]) -> dbm * * Open a dbm database with the specified name, which can include a directory * path. Any file extensions needed will be supplied automatically by the dbm * library. For example, Berkeley DB appends '.db', and GNU gdbm uses two * physical files with extensions '.dir' and '.pag'. * * The mode should be an integer, as for Unix chmod. * * Flags should be one of READER, WRITER, WRCREAT or NEWDB. */ static VALUE fdbm_initialize(int argc, VALUE *argv, VALUE obj) { volatile VALUE file; VALUE vmode, vflags; DBM *dbm; struct dbmdata *dbmp; int mode, flags = 0; if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) { mode = 0666; /* default value */ } else if (NIL_P(vmode)) { mode = -1; /* return nil if DB not exist */ } else { mode = NUM2INT(vmode); } if (!NIL_P(vflags)) flags = NUM2INT(vflags); FilePathValue(file); if (flags & RUBY_DBM_RW_BIT) { flags &= ~RUBY_DBM_RW_BIT; dbm = dbm_open(RSTRING_PTR(file), flags, mode); } else { dbm = 0; if (mode >= 0) { dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT, mode); } if (!dbm) { dbm = dbm_open(RSTRING_PTR(file), O_RDWR, 0); } if (!dbm) { dbm = dbm_open(RSTRING_PTR(file), O_RDONLY, 0); } } if (!dbm) { if (mode == -1) return Qnil; rb_sys_fail(RSTRING_PTR(file)); } dbmp = ALLOC(struct dbmdata); DATA_PTR(obj) = dbmp; dbmp->di_dbm = dbm; dbmp->di_size = -1; return obj; }
static CFURLRef str_to_url(VALUE path) { #ifdef FilePathValue VALUE p = FilePathValue(path); #else VALUE p = rb_String(path); #endif CFURLRef fileURL = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)RSTRING_PTR(p), RSTRING_LEN(p), false); if (!fileURL) { rb_raise(rb_eArgError, "Unable to create CFURL from `%s'.", RSTRING_PTR(rb_inspect(path))); } return fileURL; }
// 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; rb_scan_args(argc, argv, "11", &fname, &wrap); path = rb_find_file(FilePathValue(fname)); if (!path) { if (!rb_file_load_ok(RSTRING_PTR(fname))) load_failed(fname); path = fname; } rb_load_internal(path, RTEST(wrap)); return Qtrue; }
/* * call-seq: * SDBM.new(filename, mode = 0666) * * Creates a new database handle by opening the given +filename+. SDBM actually * uses two physical files, with extensions '.dir' and '.pag'. These extensions * will automatically be appended to the +filename+. * * If the file does not exist, a new file will be created using the given * +mode+, unless +mode+ is explicitly set to nil. In the latter case, no * database will be created. * * If the file exists, it will be opened in read/write mode. If this fails, it * will be opened in read-only mode. */ static VALUE fsdbm_initialize(int argc, VALUE *argv, VALUE obj) { volatile VALUE file; VALUE vmode; DBM *dbm; struct dbmdata *dbmp; int mode; if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) { mode = 0666; /* default value */ } else if (NIL_P(vmode)) { mode = -1; /* return nil if DB not exist */ } else { mode = NUM2INT(vmode); } FilePathValue(file); dbm = 0; if (mode >= 0) dbm = sdbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT, mode); if (!dbm) dbm = sdbm_open(RSTRING_PTR(file), O_RDWR, 0); if (!dbm) dbm = sdbm_open(RSTRING_PTR(file), O_RDONLY, 0); if (!dbm) { if (mode == -1) return Qnil; rb_sys_fail_str(file); } dbmp = ALLOC(struct dbmdata); DATA_PTR(obj) = dbmp; dbmp->di_dbm = dbm; dbmp->di_size = -1; return obj; }
void rb_load(VALUE fname, int wrap) { #if MACRUBY_STATIC rb_raise(rb_eRuntimeError, "#load is not supported in MacRuby static"); #else // TODO honor wrap // Locate file. FilePathValue(fname); fname = rb_str_new4(fname); VALUE tmp = rb_find_file(fname); if (tmp == 0) { load_failed(fname); } fname = tmp; // Load it. const char *fname_str = RSTRING_PTR(fname); //printf("load %s\n", fname_str); rb_vm_load(fname_str, wrap); #endif }
/* * call-seq: * Dir.chdir( [ string] ) => 0 * Dir.chdir( [ string] ) {| path | block } => anObject * * Changes the current working directory of the process to the given * string. When called without an argument, changes the directory to * the value of the environment variable <code>HOME</code>, or * <code>LOGDIR</code>. <code>SystemCallError</code> (probably * <code>Errno::ENOENT</code>) if the target directory does not exist. * * If a block is given, it is passed the name of the new current * directory, and the block is executed with that as the current * directory. The original working directory is restored when the block * exits. The return value of <code>chdir</code> is the value of the * block. <code>chdir</code> blocks can be nested, but in a * multi-threaded program an error will be raised if a thread attempts * to open a <code>chdir</code> block while another thread has one * open. * * Dir.chdir("/var/spool/mail") * puts Dir.pwd * Dir.chdir("/tmp") do * puts Dir.pwd * Dir.chdir("/usr") do * puts Dir.pwd * end * puts Dir.pwd * end * puts Dir.pwd * * <em>produces:</em> * * /var/spool/mail * /tmp * /usr * /tmp * /var/spool/mail */ static VALUE dir_s_chdir(int argc, VALUE *argv, VALUE obj) { VALUE path = Qnil; rb_secure(2); if (rb_scan_args(argc, argv, "01", &path) == 1) { FilePathValue(path); } else { const char *dist = getenv("HOME"); if (!dist) { dist = getenv("LOGDIR"); if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set"); } path = rb_str_new2(dist); } if (chdir_blocking > 0) { if (!rb_block_given_p() || rb_thread_current() != chdir_thread) rb_warn("conflicting chdir during another chdir block"); } if (rb_block_given_p()) { struct chdir_data args; char *cwd = my_getcwd(); args.old_path = rb_tainted_str_new2(cwd); xfree(cwd); args.new_path = path; args.done = Qfalse; return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args); } dir_chdir(path); return INT2FIX(0); }
/* * call-seq: * DBM.new(filename[, mode[, flags]]) -> dbm * * Open a dbm database with the specified name, which can include a directory * path. Any file extensions needed will be supplied automatically by the dbm * library. For example, Berkeley DB appends '.db', and GNU gdbm uses two * physical files with extensions '.dir' and '.pag'. * * The mode should be an integer, as for Unix chmod. * * Flags should be one of READER, WRITER, WRCREAT or NEWDB. */ static VALUE fdbm_initialize(int argc, VALUE *argv, VALUE obj) { volatile VALUE file; VALUE vmode, vflags; DBM *dbm; struct dbmdata *dbmp; int mode, flags = 0; if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) { mode = 0666; /* default value */ } else if (NIL_P(vmode)) { mode = -1; /* return nil if DB not exist */ } else { mode = NUM2INT(vmode); } if (!NIL_P(vflags)) flags = NUM2INT(vflags); FilePathValue(file); /* * Note: * gdbm 1.10 works with O_CLOEXEC. gdbm 1.9.1 silently ignore it. */ #ifndef O_CLOEXEC # define O_CLOEXEC 0 #endif if (flags & RUBY_DBM_RW_BIT) { flags &= ~RUBY_DBM_RW_BIT; dbm = dbm_open(RSTRING_PTR(file), flags|O_CLOEXEC, mode); } else { dbm = 0; if (mode >= 0) { dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT|O_CLOEXEC, mode); } if (!dbm) { dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CLOEXEC, 0); } if (!dbm) { dbm = dbm_open(RSTRING_PTR(file), O_RDONLY|O_CLOEXEC, 0); } } if (dbm) { /* * History of dbm_pagfno() and dbm_dirfno() in ndbm and its compatibles. * (dbm_pagfno() and dbm_dirfno() is not standardized.) * * 1986: 4.3BSD provides ndbm. * It provides dbm_pagfno() and dbm_dirfno() as macros. * 1991: gdbm-1.5 provides them as functions. * They returns a same descriptor. * (Earlier releases may have the functions too.) * 1991: Net/2 provides Berkeley DB. * It doesn't provide dbm_pagfno() and dbm_dirfno(). * 1992: 4.4BSD Alpha provides Berkeley DB with dbm_dirfno() as a function. * dbm_pagfno() is a macro as DBM_PAGFNO_NOT_AVAILABLE. * 1997: Berkeley DB 2.0 is released by Sleepycat Software, Inc. * It defines dbm_pagfno() and dbm_dirfno() as macros. * 2011: gdbm-1.9 creates a separate dir file. * dbm_pagfno() and dbm_dirfno() returns different descriptors. */ #if defined(HAVE_DBM_PAGFNO) rb_fd_fix_cloexec(dbm_pagfno(dbm)); #endif #if defined(HAVE_DBM_DIRFNO) rb_fd_fix_cloexec(dbm_dirfno(dbm)); #endif #if defined(RUBYDBM_DB_HEADER) && defined(HAVE_TYPE_DBC) /* Disable Berkeley DB error messages such as: * DB->put: attempt to modify a read-only database */ ((DBC*)dbm)->dbp->set_errfile(((DBC*)dbm)->dbp, NULL); #endif } if (!dbm) { if (mode == -1) return Qnil; rb_sys_fail_str(file); } dbmp = ALLOC(struct dbmdata); DATA_PTR(obj) = dbmp; dbmp->di_dbm = dbm; dbmp->di_size = -1; return obj; }
/* * 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; }
/* * call-seq: * Dir.new( string ) -> aDir * * Returns a new directory object for the named directory. */ static VALUE dir_initialize(int argc, VALUE *argv, VALUE dir) { struct dir_data *dp; static rb_encoding *fs_encoding; rb_encoding *intencoding, *extencoding; VALUE dirname, opt; static VALUE sym_intenc, sym_extenc; if (!sym_intenc) { sym_intenc = ID2SYM(rb_intern("internal_encoding")); sym_extenc = ID2SYM(rb_intern("external_encoding")); fs_encoding = rb_filesystem_encoding(); } intencoding = NULL; extencoding = fs_encoding; rb_scan_args(argc, argv, "11", &dirname, &opt); if (!NIL_P(opt)) { VALUE v, extenc=Qnil, intenc=Qnil; opt = rb_check_convert_type(opt, T_HASH, "Hash", "to_hash"); v = rb_hash_aref(opt, sym_intenc); if (!NIL_P(v)) intenc = v; v = rb_hash_aref(opt, sym_extenc); if (!NIL_P(v)) extenc = v; if (!NIL_P(extenc)) { extencoding = rb_to_encoding(extenc); if (!NIL_P(intenc)) { intencoding = rb_to_encoding(intenc); if (extencoding == intencoding) { rb_warn("Ignoring internal encoding '%s': it is identical to external encoding '%s'", RSTRING_PTR(rb_inspect(intenc)), RSTRING_PTR(rb_inspect(extenc))); intencoding = NULL; } } } else if (!NIL_P(intenc)) { rb_raise(rb_eArgError, "External encoding must be specified when internal encoding is given"); } } { rb_encoding *dirname_encoding = rb_enc_get(dirname); if (rb_usascii_encoding() != dirname_encoding && rb_ascii8bit_encoding() != dirname_encoding #if defined __APPLE__ && rb_utf8_encoding() != dirname_encoding #endif && extencoding != dirname_encoding) { if (!intencoding) intencoding = dirname_encoding; dirname = rb_str_transcode(dirname, rb_enc_from_encoding(extencoding)); } } FilePathValue(dirname); Data_Get_Struct(dir, struct dir_data, dp); if (dp->dir) closedir(dp->dir); if (dp->path) xfree(dp->path); dp->dir = NULL; dp->path = NULL; dp->intenc = intencoding; dp->extenc = extencoding; dp->dir = opendir(RSTRING_PTR(dirname)); if (dp->dir == NULL) { if (errno == EMFILE || errno == ENFILE) { rb_gc(); dp->dir = opendir(RSTRING_PTR(dirname)); } if (dp->dir == NULL) { rb_sys_fail(RSTRING_PTR(dirname)); } } dp->path = strdup(RSTRING_PTR(dirname)); return dir; }