Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
Dir.fchdir
static VALUE
dir_s_fchdir(VALUE klass, VALUE fd_value)
{
int fd = RB_NUM2INT(fd_value);
if (chdir_alone_block_p()) {
struct fchdir_data args;
args.old_dir = dir_s_alloc(klass);
dir_initialize(NULL, args.old_dir, rb_fstring_cstr("."), Qnil);
args.fd = fd;
args.done = FALSE;
return rb_ensure(fchdir_yield, (VALUE)&args, fchdir_restore, (VALUE)&args);
}
else {
int r = IO_WITHOUT_GVL_INT(nogvl_fchdir, &fd);
if (r < 0)
rb_sys_fail("fchdir");
}
return INT2FIX(0);
}
Changes the current working directory to the directory specified by the integer file descriptor fd.
When passing a file descriptor over a UNIX socket or to a child process, using fchdir instead of chdir avoids the time-of-check to time-of-use vulnerability
With no block, changes to the directory given by fd:
Dir.chdir('/var/spool/mail') Dir.pwd # => "/var/spool/mail" dir = Dir.new('/usr') fd = dir.fileno Dir.fchdir(fd) Dir.pwd # => "/usr"
With a block, temporarily changes the working directory:
-
Calls the block with the argument.
-
Changes to the given directory.
-
Executes the block (yields no args).
-
Restores the previous working directory.
-
Returns the block’s return value.
Example:
Dir.chdir('/var/spool/mail') Dir.pwd # => "/var/spool/mail" dir = Dir.new('/tmp') fd = dir.fileno Dir.fchdir(fd) do Dir.pwd # => "/tmp" end Dir.pwd # => "/var/spool/mail"
This method uses the fchdir() function defined by POSIX 2008; the method is not implemented on non-POSIX platforms (raises NotImplementedError).
Raises an exception if the file descriptor is not valid.
In a multi-threaded program an error is raised if a thread attempts to open a chdir block while another thread has one open, or a call to chdir without a block occurs inside a block passed to chdir (even in the same thread).
Ruby version changes
-
3.3
-
Dir.fchdiradded for changing the directory to the directory specified by the provided directory file descriptor. [Feature #19347]
-