summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2023-02-09 12:45:52 -0800
committerJeremy Evans <code@jeremyevans.net>2023-03-24 11:18:57 -0700
commit3be65f63c79492908e898d8d7281035445a2b9a1 (patch)
treed26c29069be936a0f8de84b1105f96b5da3479ea /dir.c
parent466ca7ae205126c7cac83735db887d69e293f816 (diff)
downloadruby-3be65f63c79492908e898d8d7281035445a2b9a1.tar.gz
Add Dir#chdir
This uses Dir.fchdir if supported, or Dir.chdir otherwise. Implements [Feature #19347]
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/dir.c b/dir.c
index c32e9de415..93f2657eb0 100644
--- a/dir.c
+++ b/dir.c
@@ -972,7 +972,7 @@ nogvl_chdir(void *ptr)
}
static void
-dir_chdir(VALUE path)
+dir_chdir0(VALUE path)
{
if (chdir(RSTRING_PTR(path)) < 0)
rb_sys_fail_path(path);
@@ -990,7 +990,7 @@ static VALUE
chdir_yield(VALUE v)
{
struct chdir_data *args = (void *)v;
- dir_chdir(args->new_path);
+ dir_chdir0(args->new_path);
args->done = TRUE;
chdir_blocking++;
if (NIL_P(chdir_thread))
@@ -1006,7 +1006,7 @@ chdir_restore(VALUE v)
chdir_blocking--;
if (chdir_blocking == 0)
chdir_thread = Qnil;
- dir_chdir(args->old_path);
+ dir_chdir0(args->old_path);
}
return Qnil;
}
@@ -1223,6 +1223,30 @@ dir_s_fchdir(VALUE klass, VALUE fd_value)
#define dir_s_fchdir rb_f_notimplement
#endif
+/*
+ * call-seq:
+ * dir.chdir -> nil
+ *
+ * Changes the current working directory to the receiver.
+ *
+ * # Assume current directory is /path
+ * Dir.new("testdir").chdir
+ * Dir.pwd # => '/path/testdir'
+ */
+static VALUE
+dir_chdir(VALUE dir)
+{
+#if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD
+ dir_s_fchdir(rb_cDir, dir_fileno(dir));
+#else
+ struct dir_data *dirp;
+ dirp = dir_get(dir);
+ dir_s_chdir(1, &dirp->path, rb_cDir);
+#endif
+
+ return Qnil;
+}
+
#ifndef _WIN32
VALUE
rb_dir_getwd_ospath(void)
@@ -3502,6 +3526,7 @@ Init_Dir(void)
rb_define_method(rb_cDir,"pos", dir_tell, 0);
rb_define_method(rb_cDir,"pos=", dir_set_pos, 1);
rb_define_method(rb_cDir,"close", dir_close, 0);
+ rb_define_method(rb_cDir,"chdir", dir_chdir, 0);
rb_define_singleton_method(rb_cDir,"fchdir", dir_s_fchdir, 1);
rb_define_singleton_method(rb_cDir,"chdir", dir_s_chdir, -1);