From 00f9231534d9a9c19d68857f62343b5af28036f9 Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Wed, 5 Jul 2023 08:45:54 -0500 Subject: [PATCH] [DOC] RDoc for some of dir.c (#8026) --- dir.c | 396 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 226 insertions(+), 170 deletions(-) diff --git a/dir.c b/dir.c index fc7d9049fc..c25b067b89 100644 --- a/dir.c +++ b/dir.c @@ -590,23 +590,24 @@ dir_s_close(rb_execution_context_t *ec, VALUE klass, VALUE dir) # if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD) /* - * call-seq: - * Dir.for_fd(integer) -> aDir + * call-seq: + * Dir.for_fd(fd) -> dir * - * Returns a Dir representing the directory specified by the given - * directory file descriptor. Note that the returned Dir will not - * have an associated path. + * Returns a new \Dir object representing the directory specified by the given + * integer directory file descriptor +fd+: * - * d1 = Dir.new('..') - * d2 = Dir.for_fd(d1.fileno) - * d1.path # => '..' - * d2.path # => nil - * d1.chdir{Dir.pwd} == d2.chdir{Dir.pwd} # => true + * d0 = Dir.new('..') + * d1 = Dir.for_fd(d0.fileno) * - * This method uses fdopendir() function defined by POSIX 2008. - * NotImplementedError is raised on other platforms, such as Windows, - * which doesn't provide the function. + * Note that the returned +d1+ does not have an associated path: * + * d0.path # => '..' + * d1.path # => nil + * + * This method uses the + * {fdopendir()}[https://www.man7.org/linux/man-pages/man3/fdopendir.3p.html] + * function defined by POSIX 2008; + * the method is not implemented on non-POSIX platforms (raises NotImplementedError). */ static VALUE dir_s_for_fd(VALUE klass, VALUE fd) @@ -653,10 +654,13 @@ dir_check(VALUE dir) /* - * call-seq: - * dir.inspect -> string + * call-seq: + * inspect -> string + * + * Returns a string description of +self+: + * + * Dir.new('example').inspect # => "#" * - * Return a string describing this Dir object. */ static VALUE dir_inspect(VALUE dir) @@ -690,18 +694,18 @@ dir_inspect(VALUE dir) #ifdef HAVE_DIRFD /* - * call-seq: - * dir.fileno -> integer + * call-seq: + * fileno -> integer * - * Returns the file descriptor used in dir. + * Returns the file descriptor used in dir. * - * d = Dir.new("..") - * d.fileno #=> 8 - * - * This method uses dirfd() function defined by POSIX 2008. - * NotImplementedError is raised on other platforms, such as Windows, - * which doesn't provide the function. + * d = Dir.new('..') + * d.fileno # => 8 * + * This method uses the + * {dirfd()}[https://www.man7.org/linux/man-pages/man3/dirfd.3.html] + * function defined by POSIX 2008; + * the method is not implemented on non-POSIX platforms (raises NotImplementedError). */ static VALUE dir_fileno(VALUE dir) @@ -720,14 +724,14 @@ dir_fileno(VALUE dir) #endif /* - * call-seq: - * dir.path -> string or nil - * dir.to_path -> string or nil + * call-seq: + * path -> string or nil * - * Returns the path parameter passed to dir's constructor. + * Returns the +dirpath+ string that was used to create +self+ + * (or +nil+ if created by method Dir.for_fd): + * + * Dir.new('example').path # => "example" * - * d = Dir.new("..") - * d.path #=> ".." */ static VALUE dir_path(VALUE dir) @@ -781,16 +785,18 @@ to_be_skipped(const struct dirent *dp) } /* - * call-seq: - * dir.read -> string or nil + * call-seq: + * read -> string or nil * - * Reads the next entry from dir and returns it as a string. - * Returns nil at the end of the stream. + * Reads and returns the next entry name from +self+; + * returns +nil+ if at end-of-stream; + * see {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like]: + * + * dir = Dir.new('example') + * dir.read # => "." + * dir.read # => ".." + * dir.read # => "config.h" * - * d = Dir.new("testdir") - * d.read #=> "." - * d.read #=> ".." - * d.read #=> "config.h" */ static VALUE dir_read(VALUE dir) @@ -819,24 +825,23 @@ dir_yield(VALUE arg, VALUE path) } /* - * call-seq: - * dir.each { |filename| block } -> dir - * dir.each -> an_enumerator + * call-seq: + * each {|entry_name| ... } -> self * - * Calls the block once for each entry in this directory, passing the - * filename of each entry as a parameter to the block. + * Calls the block with each entry name in +self+: * - * If no block is given, an enumerator is returned instead. + * Dir.new('example').each {|entry_name| p entry_name } * - * d = Dir.new("testdir") - * d.each {|x| puts "Got #{x}" } + * Output: + + * "." + * ".." + * "config.h" + * "lib" + * "main.rb" * - * produces: + * With no block given, returns an Enumerator. * - * Got . - * Got .. - * Got config.h - * Got main.rb */ static VALUE dir_each(VALUE dir) @@ -879,16 +884,17 @@ dir_each_entry(VALUE dir, VALUE (*each)(VALUE, VALUE), VALUE arg, int children_o #ifdef HAVE_TELLDIR /* - * call-seq: - * dir.pos -> integer - * dir.tell -> integer + * call-seq: + * tell -> integer * - * Returns the current position in dir. See also Dir#seek. + * Returns the current position of +self+; + * see {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like]: + * + * dir = Dir.new('example') + * dir.tell # => 0 + * dir.read # => "." + * dir.tell # => 1 * - * d = Dir.new("testdir") - * d.tell #=> 0 - * d.read #=> "." - * d.tell #=> 12 */ static VALUE dir_tell(VALUE dir) @@ -906,18 +912,24 @@ dir_tell(VALUE dir) #ifdef HAVE_SEEKDIR /* - * call-seq: - * dir.seek( integer ) -> dir + * call-seq: + * seek(position) -> self * - * Seeks to a particular location in dir. integer - * must be a value returned by Dir#tell. + * Sets the position in +self+ and returns +self+. + * The value of +position+ should have been returned from an earlier call to #tell; + * if not, the return values from subsequent calls to #read are unspecified. + * + * See {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like]. + * + * Examples: + * + * dir = Dir.new('example') + * dir.pos # => 0 + * dir.seek(3) # => # + * dir.pos # => 3 + * dir.seek(30) # => # + * dir.pos # => 5 * - * d = Dir.new("testdir") #=> # - * d.read #=> "." - * i = d.tell #=> 12 - * d.read #=> ".." - * d.seek(i) #=> # - * d.read #=> ".." */ static VALUE dir_seek(VALUE dir, VALUE pos) @@ -935,17 +947,24 @@ dir_seek(VALUE dir, VALUE pos) #ifdef HAVE_SEEKDIR /* - * call-seq: - * dir.pos = integer -> integer + * call-seq: + * pos = position -> integer * - * Synonym for Dir#seek, but returns the position parameter. + * Sets the position in +self+ and returns +position+. + * The value of +position+ should have been returned from an earlier call to #tell; + * if not, the return values from subsequent calls to #read are unspecified. + * + * See {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like]. + * + * Examples: + * + * dir = Dir.new('example') + * dir.pos # => 0 + * dir.pos = 3 # => 3 + * dir.pos # => 3 + * dir.pos = 30 # => 30 + * dir.pos # => 5 * - * d = Dir.new("testdir") #=> # - * d.read #=> "." - * i = d.pos #=> 12 - * d.read #=> ".." - * d.pos = i #=> 12 - * d.read #=> ".." */ static VALUE dir_set_pos(VALUE dir, VALUE pos) @@ -958,15 +977,19 @@ dir_set_pos(VALUE dir, VALUE pos) #endif /* - * call-seq: - * dir.rewind -> dir + * call-seq: + * rewind -> self * - * Repositions dir to the first entry. + * Sets the position in +self+ to zero; + * see {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like]: + * + * dir = Dir.new('example') + * dir.read # => "." + * dir.read # => ".." + * dir.pos # => 2 + * dir.rewind # => # + * dir.pos # => 0 * - * d = Dir.new("testdir") - * d.read #=> "." - * d.rewind #=> # - * d.read #=> "." */ static VALUE dir_rewind(VALUE dir) @@ -979,14 +1002,18 @@ dir_rewind(VALUE dir) } /* - * call-seq: - * dir.close -> nil + * call-seq: + * close -> nil * - * Closes the directory stream. - * Calling this method on closed Dir object is ignored since Ruby 2.3. + * Closes the stream in +self+, if it is open, and returns +nil+; + * ignored if +self+ is already closed: + * + * dir = Dir.new('example') + * dir.read # => "." + * dir.close # => nil + * dir.close # => nil + * dir.read # Raises IOError. * - * d = Dir.new("testdir") - * d.close #=> nil */ static VALUE dir_close(VALUE dir) @@ -1050,44 +1077,67 @@ chdir_restore(VALUE v) } /* - * call-seq: - * Dir.chdir( [ string] ) -> 0 - * Dir.chdir( [ string] ) {| path | block } -> anObject + * call-seq: + * Dir.chdir(new_dirpath) -> 0 + * Dir.chdir -> 0 + * Dir.chdir(new_dirpath) {|new_dirpath| ... } -> object + * Dir.chdir {|cur_dirpath| ... } -> object * - * 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 HOME, or - * LOGDIR. SystemCallError (probably Errno::ENOENT) if - * the target directory does not exist. + * Changes the current working directory. * - * 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 chdir is the value of the - * block. chdir blocks can be nested, but in a - * multi-threaded program an error will be 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). + * With argument +new_dirpath+ and no block, + * changes to the given +dirpath+: * - * 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 + * Dir.pwd # => "/example" + * Dir.chdir('..') # => 0 + * Dir.pwd # => "/" + * + * With no argument and no block: + * + * - Changes to the value of environment variable +HOME+ if defined. + * - Otherwise changes to the value of environment variable +LOGDIR+ if defined. + * - Otherwise makes no change. + * + * With argument +new_dirpath+ and a block, temporarily changes the working directory: + * + * - Calls the block with the argument. + * - Changes to the given directory. + * - Executes the block + * - Restores the previous working directory. + * - Returns the block's return value. + * + * Example: + * + * Dir.chdir('/var/spool/mail') + * Dir.pwd # => "/var/spool/mail" + * Dir.chdir('/tmp') do + * Dir.pwd # => "/tmp" + * end + * Dir.pwd # => "/var/spool/mail" + * + * With no argument and a block, + * calls the block with the current working directory (string) + * and returns the block's return value. + * + * Calls to \Dir.chdir with blocks may be nested: + * + * Dir.chdir('/var/spool/mail') + * Dir.pwd # => "/var/spool/mail" + * Dir.chdir('/tmp') do + * Dir.pwd # => "/tmp" + * Dir.chdir('/usr') do + * Dir.pwd # => "/usr" * end - * puts Dir.pwd + * Dir.pwd # => "/tmp" + * end + * Dir.pwd # => "/var/spool/mail" * - * produces: + * 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). * - * /var/spool/mail - * /tmp - * /usr - * /tmp - * /var/spool/mail + * Raises an exception if the target directory does not exist. */ static VALUE dir_s_chdir(int argc, VALUE *argv, VALUE obj) @@ -1181,52 +1231,56 @@ fchdir_restore(VALUE v) } /* - * call-seq: - * Dir.fchdir( integer ) -> 0 - * Dir.fchdir( integer ) { block } -> anObject + * call-seq: + * Dir.fchdir(fd) -> 0 + * Dir.fchdir(fd) { ... } -> object * - * Changes the current working directory of the process to the directory - * specified by the given file descriptor integer. If the file descriptor - * is not valid, raises SystemCallError. One reason to use - * fchdir instead of chdir is when passing - * directory file descriptors over a UNIX socket or to child processes, - * to avoid TOCTOU (time-of-check to time-of-use) vulnerabilities. + * Changes the current working directory to the directory + * specified by the integer file descriptor +fd+. * - * If a block is given, the current working directory is changed for the - * duration of the block, and the original working directory is restored - * when the block exits. The return value of fchdir is the - * value of the block. fchdir and chdir blocks - * can be nested, but in a multi-threaded program an error will be raised - * if a thread attempts to open a fchdir or chdir - * block while another thread has one open or a call to fchdir - * or chdir without a block occurs inside a block passed to - * fchdir or chdir (even in the same thread). + * 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}[https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use] * - * When generating directory file descriptors from a +Dir+ instance, - * make sure the +Dir+ instance is not garbage collected before the - * directory file descriptor is passed to another process. Otherwise, - * the directory file descriptor will be closed before it is passed. + * With no block, changes to the directory given by +fd+: * - * dir = Dir.new("/var/spool/mail") - * dir2 = Dir.new("/usr") - * fd = dir.fileno - * fd2 = dir2.fileno - * Dir.fchdir(fd) do - * puts Dir.pwd - * Dir.fchdir(fd2) do - * puts Dir.pwd - * end - * puts Dir.pwd - * end - * puts Dir.pwd + * Dir.chdir('/var/spool/mail') + * Dir.pwd # => "/var/spool/mail" + * dir = Dir.new('/usr') + * fd = dir.fileno + * Dir.fchdir(fd) do + * Dir.pwd # => "/usr" + * end + * Dir.pwd # => "/var/spool/mail" * - * produces: + * With a block, temporarily changes the working directory: * - * /var/spool/mail - * /tmp - * /usr - * /tmp - * /var/spool/mail + * - Calls the block with the argument. + * - Changes to the given directory. + * - Executes the block + * - Restores the previous working directory. + * - Returns the block's return value. + * + * Example: + * + * Dir.chdir('/var/spool/mail') + * Dir.pwd # => "/var/spool/mail" + * Dir.chdir('/tmp') do + * Dir.pwd # => "/tmp" + * end + * Dir.pwd # => "/var/spool/mail" + * + * This method uses the + * {fchdir()}[https://www.man7.org/linux/man-pages/man3/fchdir.3p.html] + * 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). */ static VALUE dir_s_fchdir(VALUE klass, VALUE fd_value) @@ -1262,14 +1316,16 @@ dir_s_fchdir(VALUE klass, VALUE fd_value) #endif /* - * call-seq: - * dir.chdir -> nil + * call-seq: + * chdir -> nil * - * Changes the current working directory to the receiver. + * Changes the current working directory to the path of +self+: + * + * Dir.pwd # => "/" + * dir = Dir.new('example') + * dir.chdir + * dir.pwd # => "/example" * - * # Assume current directory is /path - * Dir.new("testdir").chdir - * Dir.pwd # => '/path/testdir' */ static VALUE dir_chdir(VALUE dir)