@@ -364,6 +364,61 @@ class Dir
364364 #
365365 def self.exist? : (path | io file_name) -> bool
366366
367+ # <!--
368+ # rdoc-file=dir.c
369+ # - Dir.fchdir(fd) -> 0
370+ # - Dir.fchdir(fd) { ... } -> object
371+ # -->
372+ # Changes the current working directory to the directory specified by the
373+ # integer file descriptor `fd`.
374+ #
375+ # When passing a file descriptor over a UNIX socket or to a child process, using
376+ # `fchdir` instead of `chdir` avoids the [time-of-check to time-of-use
377+ # vulnerability](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use)
378+ #
379+ # With no block, changes to the directory given by `fd`:
380+ #
381+ # Dir.chdir('/var/spool/mail')
382+ # Dir.pwd # => "/var/spool/mail"
383+ # dir = Dir.new('/usr')
384+ # fd = dir.fileno
385+ # Dir.fchdir(fd) do
386+ # Dir.pwd # => "/usr"
387+ # end
388+ # Dir.pwd # => "/var/spool/mail"
389+ #
390+ # With a block, temporarily changes the working directory:
391+ #
392+ # * Calls the block with the argument.
393+ # * Changes to the given directory.
394+ # * Executes the block
395+ # * Restores the previous working directory.
396+ # * Returns the block's return value.
397+ #
398+ #
399+ # Example:
400+ #
401+ # Dir.chdir('/var/spool/mail')
402+ # Dir.pwd # => "/var/spool/mail"
403+ # Dir.chdir('/tmp') do
404+ # Dir.pwd # => "/tmp"
405+ # end
406+ # Dir.pwd # => "/var/spool/mail"
407+ #
408+ # This method uses the
409+ # [fchdir()](https://www.man7.org/linux/man-pages/man3/fchdir.3p.html) function
410+ # defined by POSIX 2008; the method is not implemented on non-POSIX platforms
411+ # (raises NotImplementedError).
412+ #
413+ # Raises an exception if the file descriptor is not valid.
414+ #
415+ # In a multi-threaded program an error is raised if a thread attempts to open a
416+ # `chdir` block while another thread has one open, or a call to `chdir` without
417+ # a block occurs inside a block passed to `chdir` (even in the same thread).
418+ #
419+ def self.fchdir : (int) -> Integer
420+ | [T] (int) { () -> T } -> T
421+
367422 # <!--
368423 # rdoc-file=dir.c
369424 # - Dir.foreach(dirpath, encoding: 'UTF-8') {|entry_name| ... } -> nil
@@ -397,6 +452,28 @@ class Dir
397452 #
398453 alias self .foreach self .each_child
399454
455+ # <!--
456+ # rdoc-file=dir.c
457+ # - Dir.for_fd(fd) -> dir
458+ # -->
459+ # Returns a new Dir object representing the directory specified by the given
460+ # integer directory file descriptor `fd`:
461+ #
462+ # d0 = Dir.new('..')
463+ # d1 = Dir.for_fd(d0.fileno)
464+ #
465+ # Note that the returned `d1` does not have an associated path:
466+ #
467+ # d0.path # => '..'
468+ # d1.path # => nil
469+ #
470+ # This method uses the
471+ # [fdopendir()](https://www.man7.org/linux/man-pages/man3/fdopendir.3p.html)
472+ # function defined by POSIX 2008; the method is not implemented on non-POSIX
473+ # platforms (raises NotImplementedError).
474+ #
475+ def self.for_fd : (int) -> Dir
476+
400477 # <!--
401478 # rdoc-file=dir.c
402479 # - Dir.pwd -> string
@@ -678,6 +755,20 @@ class Dir
678755
679756 public
680757
758+ # <!--
759+ # rdoc-file=dir.c
760+ # - chdir -> nil
761+ # -->
762+ # Changes the current working directory to the path of `self`:
763+ #
764+ # Dir.pwd # => "/"
765+ # dir = Dir.new('example')
766+ # dir.chdir
767+ # dir.pwd # => "/example"
768+ #
769+ def chdir : () -> Integer
770+ | [T] { () -> T } -> T
771+
681772 # <!--
682773 # rdoc-file=dir.c
683774 # - children -> array
0 commit comments