2000-05-01 13:42:38 +04:00
|
|
|
/**********************************************************************
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
file.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
created at: Mon Nov 15 12:24:34 JST 1993
|
|
|
|
|
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
|
|
|
Copyright (C) 1993-2007 Yukihiro Matsumoto
|
2000-05-01 13:42:38 +04:00
|
|
|
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
2000-05-09 08:53:16 +04:00
|
|
|
Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-05-01 13:42:38 +04:00
|
|
|
**********************************************************************/
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2020-05-08 12:31:09 +03:00
|
|
|
#include "ruby/internal/config.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
|
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-15 06:18:08 +03:00
|
|
|
#ifdef _WIN32
|
2019-12-04 11:16:30 +03:00
|
|
|
# include "missing/file.h"
|
|
|
|
# include "ruby.h"
|
1999-01-20 07:59:39 +03:00
|
|
|
#endif
|
2019-12-04 11:16:30 +03:00
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2008-05-15 10:34:02 +04:00
|
|
|
#ifdef __CYGWIN__
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <windows.h>
|
|
|
|
# include <sys/cygwin.h>
|
|
|
|
# include <wchar.h>
|
2008-05-15 10:34:02 +04:00
|
|
|
#endif
|
2019-12-04 11:16:30 +03:00
|
|
|
|
2013-08-09 07:06:53 +04:00
|
|
|
#ifdef __APPLE__
|
2019-06-08 13:40:55 +03:00
|
|
|
# if !(defined(__has_feature) && defined(__has_attribute))
|
|
|
|
/* Maybe a bug in SDK of Xcode 10.2.1 */
|
|
|
|
/* In this condition, <os/availability.h> does not define
|
|
|
|
* API_AVAILABLE and similar, but __API_AVAILABLE and similar which
|
|
|
|
* are defined in <Availability.h> */
|
|
|
|
# define API_AVAILABLE(...)
|
|
|
|
# define API_DEPRECATED(...)
|
|
|
|
# endif
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <CoreFoundation/CFString.h>
|
2013-08-09 07:06:53 +04:00
|
|
|
#endif
|
1999-01-20 07:59:39 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <unistd.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
2019-12-04 11:16:30 +03:00
|
|
|
|
2014-10-11 20:39:15 +04:00
|
|
|
#ifdef HAVE_SYS_TIME_H
|
|
|
|
# include <sys/time.h>
|
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-05-12 13:07:57 +04:00
|
|
|
#ifdef HAVE_SYS_FILE_H
|
|
|
|
# include <sys/file.h>
|
|
|
|
#else
|
* bignum.c: changed `foo _((boo))' to `foo(boo)`. [ruby-dev:27056]
* defines.h, dir.c, dln.h, enumerator.c, env.h, error.c, eval.c, file.c,
gc.c, hash.c, inits.c, intern.h, io.c, lex.c, marshal.c, missing.h,
node.h, numeric.c, pack.c, process.c, re.h, ruby.c, ruby.h, rubyio.h,
rubysig.h, signal.c, sprintf.c, st.h, string.c, struct.c, time.c,
util.c, util.h, variable.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9155 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-14 10:32:32 +04:00
|
|
|
int flock(int, int);
|
2000-05-12 13:07:57 +04:00
|
|
|
#endif
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
|
|
# include <sys/param.h>
|
2002-11-22 12:14:24 +03:00
|
|
|
#endif
|
|
|
|
#ifndef MAXPATHLEN
|
1998-01-16 15:13:05 +03:00
|
|
|
# define MAXPATHLEN 1024
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_UTIME_H
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <utime.h>
|
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-15 06:18:08 +03:00
|
|
|
#elif defined HAVE_SYS_UTIME_H
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <sys/utime.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_PWD_H
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <pwd.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
2016-11-03 09:02:16 +03:00
|
|
|
#ifdef HAVE_SYS_SYSMACROS_H
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <sys/sysmacros.h>
|
2016-11-03 09:02:16 +03:00
|
|
|
#endif
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
#include <sys/types.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2002-01-29 12:15:59 +03:00
|
|
|
#ifdef HAVE_SYS_MKDEV_H
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <sys/mkdev.h>
|
2002-01-29 12:15:59 +03:00
|
|
|
#endif
|
|
|
|
|
2009-03-02 15:02:22 +03:00
|
|
|
#if defined(HAVE_FCNTL_H)
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <fcntl.h>
|
2009-03-02 15:02:22 +03:00
|
|
|
#endif
|
|
|
|
|
2013-03-16 09:06:47 +04:00
|
|
|
#if defined(HAVE_SYS_TIME_H)
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <sys/time.h>
|
2013-03-16 09:06:47 +04:00
|
|
|
#endif
|
|
|
|
|
2005-04-11 17:30:10 +04:00
|
|
|
#if !defined HAVE_LSTAT && !defined lstat
|
2019-12-04 11:16:30 +03:00
|
|
|
# define lstat stat
|
1999-08-13 09:45:20 +04:00
|
|
|
#endif
|
2001-07-16 08:22:46 +04:00
|
|
|
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
/* define system APIs */
|
|
|
|
#ifdef _WIN32
|
2019-12-04 11:16:30 +03:00
|
|
|
# include "win32/file.h"
|
|
|
|
# define STAT(p, s) rb_w32_ustati128((p), (s))
|
|
|
|
# undef lstat
|
|
|
|
# define lstat(p, s) rb_w32_ulstati128((p), (s))
|
|
|
|
# undef access
|
|
|
|
# define access(p, m) rb_w32_uaccess((p), (m))
|
|
|
|
# undef truncate
|
|
|
|
# define truncate(p, n) rb_w32_utruncate((p), (n))
|
|
|
|
# undef chmod
|
|
|
|
# define chmod(p, m) rb_w32_uchmod((p), (m))
|
|
|
|
# undef chown
|
|
|
|
# define chown(p, o, g) rb_w32_uchown((p), (o), (g))
|
|
|
|
# undef lchown
|
|
|
|
# define lchown(p, o, g) rb_w32_ulchown((p), (o), (g))
|
|
|
|
# undef utimensat
|
|
|
|
# define utimensat(s, p, t, f) rb_w32_uutimensat((s), (p), (t), (f))
|
|
|
|
# undef link
|
|
|
|
# define link(f, t) rb_w32_ulink((f), (t))
|
|
|
|
# undef unlink
|
|
|
|
# define unlink(p) rb_w32_uunlink(p)
|
2022-11-17 12:57:52 +03:00
|
|
|
# undef readlink
|
|
|
|
# define readlink(f, t, l) rb_w32_ureadlink((f), (t), (l))
|
2019-12-04 11:16:30 +03:00
|
|
|
# undef rename
|
|
|
|
# define rename(f, t) rb_w32_urename((f), (t))
|
|
|
|
# undef symlink
|
|
|
|
# define symlink(s, l) rb_w32_usymlink((s), (l))
|
|
|
|
|
|
|
|
# ifdef HAVE_REALPATH
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
/* Don't use native realpath(3) on Windows, as the check for
|
|
|
|
absolute paths does not work for drive letters. */
|
2019-12-04 11:16:30 +03:00
|
|
|
# undef HAVE_REALPATH
|
|
|
|
# endif
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
#else
|
2019-12-04 11:16:30 +03:00
|
|
|
# define STAT(p, s) stat((p), (s))
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* _WIN32 */
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
|
2017-06-08 04:58:44 +03:00
|
|
|
#if defined _WIN32 || defined __APPLE__
|
|
|
|
# define USE_OSPATH 1
|
|
|
|
# define TO_OSPATH(str) rb_str_encode_ospath(str)
|
|
|
|
#else
|
|
|
|
# define USE_OSPATH 0
|
|
|
|
# define TO_OSPATH(str) (str)
|
|
|
|
#endif
|
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
/* utime may fail if time is out-of-range for the FS [ruby-dev:38277] */
|
|
|
|
#if defined DOSISH || defined __CYGWIN__
|
2019-12-04 11:16:30 +03:00
|
|
|
# define UTIME_EINVAL
|
2017-10-24 04:20:04 +03:00
|
|
|
#endif
|
|
|
|
|
2019-07-02 01:33:13 +03:00
|
|
|
/* Solaris 10 realpath(3) doesn't support File.realpath */
|
|
|
|
#if defined HAVE_REALPATH && defined __sun && defined __SVR4
|
|
|
|
#undef HAVE_REALPATH
|
|
|
|
#endif
|
|
|
|
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
#ifdef HAVE_REALPATH
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <limits.h>
|
|
|
|
# include <stdlib.h>
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
#endif
|
|
|
|
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "dln.h"
|
|
|
|
#include "encindex.h"
|
|
|
|
#include "id.h"
|
|
|
|
#include "internal.h"
|
|
|
|
#include "internal/compilers.h"
|
|
|
|
#include "internal/dir.h"
|
|
|
|
#include "internal/error.h"
|
|
|
|
#include "internal/file.h"
|
|
|
|
#include "internal/io.h"
|
|
|
|
#include "internal/load.h"
|
|
|
|
#include "internal/object.h"
|
|
|
|
#include "internal/process.h"
|
|
|
|
#include "internal/thread.h"
|
|
|
|
#include "internal/vm.h"
|
|
|
|
#include "ruby/encoding.h"
|
|
|
|
#include "ruby/thread.h"
|
|
|
|
#include "ruby/util.h"
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE rb_cFile;
|
|
|
|
VALUE rb_mFileTest;
|
2006-07-20 21:36:36 +04:00
|
|
|
VALUE rb_cStat;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2009-11-24 04:20:18 +03:00
|
|
|
static VALUE
|
2009-11-18 05:41:25 +03:00
|
|
|
file_path_convert(VALUE name)
|
|
|
|
{
|
2009-11-21 08:45:48 +03:00
|
|
|
#ifndef _WIN32 /* non Windows == Unix */
|
2015-10-17 07:31:43 +03:00
|
|
|
int fname_encidx = ENCODING_GET(name);
|
|
|
|
int fs_encidx;
|
|
|
|
if (ENCINDEX_US_ASCII != fname_encidx &&
|
2022-07-13 12:54:08 +03:00
|
|
|
ENCINDEX_ASCII_8BIT != fname_encidx &&
|
2015-10-17 07:31:43 +03:00
|
|
|
(fs_encidx = rb_filesystem_encindex()) != fname_encidx &&
|
|
|
|
rb_default_internal_encoding() &&
|
|
|
|
!rb_enc_str_asciionly_p(name)) {
|
2009-11-21 08:45:48 +03:00
|
|
|
/* Don't call rb_filesystem_encoding() before US-ASCII and ASCII-8BIT */
|
2011-12-09 10:01:41 +04:00
|
|
|
/* fs_encoding should be ascii compatible */
|
2015-10-17 07:31:43 +03:00
|
|
|
rb_encoding *fname_encoding = rb_enc_from_index(fname_encidx);
|
|
|
|
rb_encoding *fs_encoding = rb_enc_from_index(fs_encidx);
|
2009-11-18 05:41:25 +03:00
|
|
|
name = rb_str_conv_enc(name, fname_encoding, fs_encoding);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2012-10-16 05:53:32 +04:00
|
|
|
static rb_encoding *
|
|
|
|
check_path_encoding(VALUE str)
|
|
|
|
{
|
|
|
|
rb_encoding *enc = rb_enc_get(str);
|
|
|
|
if (!rb_enc_asciicompat(enc)) {
|
|
|
|
rb_raise(rb_eEncCompatError, "path name must be ASCII-compatible (%s): %"PRIsVALUE,
|
|
|
|
rb_enc_name(enc), rb_str_inspect(str));
|
|
|
|
}
|
|
|
|
return enc;
|
|
|
|
}
|
|
|
|
|
2012-11-05 19:27:08 +04:00
|
|
|
VALUE
|
2019-09-21 05:06:22 +03:00
|
|
|
rb_get_path_check_to_string(VALUE obj)
|
2004-04-07 06:51:05 +04:00
|
|
|
{
|
|
|
|
VALUE tmp;
|
2008-06-09 13:25:32 +04:00
|
|
|
ID to_path;
|
2004-04-07 06:51:05 +04:00
|
|
|
|
2012-11-05 19:27:08 +04:00
|
|
|
if (RB_TYPE_P(obj, T_STRING)) {
|
|
|
|
return obj;
|
|
|
|
}
|
2008-06-09 13:25:32 +04:00
|
|
|
CONST_ID(to_path, "to_path");
|
2017-06-01 15:58:02 +03:00
|
|
|
tmp = rb_check_funcall_default(obj, to_path, 0, 0, obj);
|
2009-11-18 05:41:25 +03:00
|
|
|
StringValue(tmp);
|
2012-11-05 19:27:08 +04:00
|
|
|
return tmp;
|
|
|
|
}
|
2010-03-25 17:22:41 +03:00
|
|
|
|
2012-11-05 19:27:08 +04:00
|
|
|
VALUE
|
2019-09-21 05:06:22 +03:00
|
|
|
rb_get_path_check_convert(VALUE obj)
|
2012-11-05 19:27:08 +04:00
|
|
|
{
|
2019-09-21 05:06:22 +03:00
|
|
|
obj = file_path_convert(obj);
|
2012-10-12 13:18:07 +04:00
|
|
|
|
2019-09-21 05:06:22 +03:00
|
|
|
check_path_encoding(obj);
|
|
|
|
if (!rb_str_to_cstr(obj)) {
|
2017-01-16 05:43:55 +03:00
|
|
|
rb_raise(rb_eArgError, "path name contains null byte");
|
|
|
|
}
|
2012-10-12 13:18:07 +04:00
|
|
|
|
2019-09-21 05:06:22 +03:00
|
|
|
return rb_str_new4(obj);
|
2012-11-05 19:27:08 +04:00
|
|
|
}
|
|
|
|
|
2007-12-09 08:12:31 +03:00
|
|
|
VALUE
|
|
|
|
rb_get_path_no_checksafe(VALUE obj)
|
|
|
|
{
|
2019-09-21 05:06:22 +03:00
|
|
|
return rb_get_path(obj);
|
2007-12-09 08:12:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_get_path(VALUE obj)
|
|
|
|
{
|
2019-09-21 05:06:22 +03:00
|
|
|
return rb_get_path_check_convert(rb_get_path_check_to_string(obj));
|
2007-12-09 08:12:31 +03:00
|
|
|
}
|
|
|
|
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
VALUE
|
|
|
|
rb_str_encode_ospath(VALUE path)
|
|
|
|
{
|
2017-06-08 04:58:44 +03:00
|
|
|
#if USE_OSPATH
|
2015-10-17 07:31:43 +03:00
|
|
|
int encidx = ENCODING_GET(path);
|
2019-12-16 05:19:59 +03:00
|
|
|
#if 0 && defined _WIN32
|
2022-07-13 12:54:08 +03:00
|
|
|
if (encidx == ENCINDEX_ASCII_8BIT) {
|
2015-10-17 07:31:43 +03:00
|
|
|
encidx = rb_filesystem_encindex();
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
}
|
2015-10-17 07:31:43 +03:00
|
|
|
#endif
|
2022-07-13 12:54:08 +03:00
|
|
|
if (encidx != ENCINDEX_ASCII_8BIT && encidx != ENCINDEX_UTF_8) {
|
2015-10-17 07:31:43 +03:00
|
|
|
rb_encoding *enc = rb_enc_from_index(encidx);
|
|
|
|
rb_encoding *utf8 = rb_utf8_encoding();
|
2013-07-26 08:02:01 +04:00
|
|
|
path = rb_str_conv_enc(path, enc, utf8);
|
2010-06-17 13:46:30 +04:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* USE_OSPATH */
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2013-08-08 05:26:27 +04:00
|
|
|
#ifdef __APPLE__
|
2016-06-12 03:24:36 +03:00
|
|
|
# define NORMALIZE_UTF8PATH 1
|
2022-09-23 21:36:04 +03:00
|
|
|
|
|
|
|
# ifdef HAVE_WORKING_FORK
|
|
|
|
static void
|
|
|
|
rb_CFString_class_initialize_before_fork(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Since macOS 13, CFString family API used in
|
|
|
|
* rb_str_append_normalized_ospath may internally use Objective-C classes
|
|
|
|
* (NSTaggedPointerString and NSPlaceholderMutableString) for small strings.
|
|
|
|
*
|
|
|
|
* On the other hand, Objective-C classes should not be used for the first
|
|
|
|
* time in a fork()'ed but not exec()'ed process. Violations for this rule
|
|
|
|
* can result deadlock during class initialization, so Objective-C runtime
|
|
|
|
* conservatively crashes on such cases by default.
|
|
|
|
*
|
|
|
|
* Therefore, we need to use CFString API to initialize Objective-C classes
|
|
|
|
* used internally *before* fork().
|
|
|
|
*
|
|
|
|
* For future changes, please note that this initialization process cannot
|
|
|
|
* be done in ctor because NSTaggedPointerString in CoreFoundation is enabled
|
|
|
|
* after CFStringInitializeTaggedStrings(), which is called during loading
|
|
|
|
* Objective-C runtime after ctor.
|
|
|
|
* For more details, see https://bugs.ruby-lang.org/issues/18912
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Enough small but non-empty ASCII string to fit in NSTaggedPointerString. */
|
|
|
|
const char small_str[] = "/";
|
|
|
|
long len = sizeof(small_str) - 1;
|
|
|
|
|
|
|
|
const CFAllocatorRef alloc = kCFAllocatorDefault;
|
|
|
|
CFStringRef s = CFStringCreateWithBytesNoCopy(alloc,
|
|
|
|
(const UInt8 *)small_str,
|
|
|
|
len, kCFStringEncodingUTF8,
|
|
|
|
FALSE, kCFAllocatorNull);
|
|
|
|
CFMutableStringRef m = CFStringCreateMutableCopy(alloc, len, s);
|
|
|
|
CFRelease(m);
|
|
|
|
CFRelease(s);
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif /* HAVE_WORKING_FORK */
|
2022-09-23 21:36:04 +03:00
|
|
|
|
2013-08-11 11:31:25 +04:00
|
|
|
static VALUE
|
2015-10-04 05:32:08 +03:00
|
|
|
rb_str_append_normalized_ospath(VALUE str, const char *ptr, long len)
|
2013-08-08 05:26:27 +04:00
|
|
|
{
|
2013-08-09 07:06:53 +04:00
|
|
|
CFIndex buflen = 0;
|
|
|
|
CFRange all;
|
|
|
|
CFStringRef s = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
|
|
|
|
(const UInt8 *)ptr, len,
|
|
|
|
kCFStringEncodingUTF8, FALSE,
|
|
|
|
kCFAllocatorNull);
|
|
|
|
CFMutableStringRef m = CFStringCreateMutableCopy(kCFAllocatorDefault, len, s);
|
2015-10-04 05:32:08 +03:00
|
|
|
long oldlen = RSTRING_LEN(str);
|
2013-08-09 07:06:53 +04:00
|
|
|
|
|
|
|
CFStringNormalize(m, kCFStringNormalizationFormC);
|
|
|
|
all = CFRangeMake(0, CFStringGetLength(m));
|
|
|
|
CFStringGetBytes(m, all, kCFStringEncodingUTF8, '?', FALSE, NULL, 0, &buflen);
|
2015-10-04 05:32:08 +03:00
|
|
|
rb_str_modify_expand(str, buflen);
|
|
|
|
CFStringGetBytes(m, all, kCFStringEncodingUTF8, '?', FALSE,
|
|
|
|
(UInt8 *)(RSTRING_PTR(str) + oldlen), buflen, &buflen);
|
|
|
|
rb_str_set_len(str, oldlen + buflen);
|
2013-08-09 07:06:53 +04:00
|
|
|
CFRelease(m);
|
|
|
|
CFRelease(s);
|
|
|
|
return str;
|
2013-08-08 05:26:27 +04:00
|
|
|
}
|
2013-08-11 00:44:10 +04:00
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_str_normalize_ospath(const char *ptr, long len)
|
|
|
|
{
|
|
|
|
const char *p = ptr;
|
|
|
|
const char *e = ptr + len;
|
|
|
|
const char *p1 = p;
|
|
|
|
VALUE str = rb_str_buf_new(len);
|
|
|
|
rb_encoding *enc = rb_utf8_encoding();
|
|
|
|
rb_enc_associate(str, enc);
|
|
|
|
|
|
|
|
while (p < e) {
|
2013-08-11 08:04:12 +04:00
|
|
|
int l, c;
|
2013-08-11 00:44:10 +04:00
|
|
|
int r = rb_enc_precise_mbclen(p, e, enc);
|
|
|
|
if (!MBCLEN_CHARFOUND_P(r)) {
|
|
|
|
/* invalid byte shall not happen but */
|
2015-10-04 05:32:08 +03:00
|
|
|
static const char invalid[3] = "\xEF\xBF\xBD";
|
|
|
|
rb_str_append_normalized_ospath(str, p1, p-p1);
|
|
|
|
rb_str_cat(str, invalid, sizeof(invalid));
|
2013-08-11 00:44:10 +04:00
|
|
|
p += 1;
|
2015-07-07 09:02:21 +03:00
|
|
|
p1 = p;
|
|
|
|
continue;
|
2013-08-11 00:44:10 +04:00
|
|
|
}
|
|
|
|
l = MBCLEN_CHARFOUND_LEN(r);
|
2013-08-11 08:04:12 +04:00
|
|
|
c = rb_enc_mbc_to_codepoint(p, e, enc);
|
2013-08-11 00:44:10 +04:00
|
|
|
if ((0x2000 <= c && c <= 0x2FFF) || (0xF900 <= c && c <= 0xFAFF) ||
|
|
|
|
(0x2F800 <= c && c <= 0x2FAFF)) {
|
|
|
|
if (p - p1 > 0) {
|
2015-10-04 05:32:08 +03:00
|
|
|
rb_str_append_normalized_ospath(str, p1, p-p1);
|
2013-08-11 00:44:10 +04:00
|
|
|
}
|
|
|
|
rb_str_cat(str, p, l);
|
|
|
|
p += l;
|
|
|
|
p1 = p;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
p += l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p - p1 > 0) {
|
2015-10-04 05:32:08 +03:00
|
|
|
rb_str_append_normalized_ospath(str, p1, p-p1);
|
2013-08-11 00:44:10 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
2014-12-25 10:01:22 +03:00
|
|
|
|
|
|
|
static int
|
|
|
|
ignored_char_p(const char *p, const char *e, rb_encoding *enc)
|
|
|
|
{
|
|
|
|
unsigned char c;
|
|
|
|
if (p+3 > e) return 0;
|
|
|
|
switch ((unsigned char)*p) {
|
|
|
|
case 0xe2:
|
|
|
|
switch ((unsigned char)p[1]) {
|
|
|
|
case 0x80:
|
|
|
|
c = (unsigned char)p[2];
|
|
|
|
/* c >= 0x200c && c <= 0x200f */
|
|
|
|
if (c >= 0x8c && c <= 0x8f) return 3;
|
|
|
|
/* c >= 0x202a && c <= 0x202e */
|
|
|
|
if (c >= 0xaa && c <= 0xae) return 3;
|
|
|
|
return 0;
|
|
|
|
case 0x81:
|
|
|
|
c = (unsigned char)p[2];
|
|
|
|
/* c >= 0x206a && c <= 0x206f */
|
|
|
|
if (c >= 0xaa && c <= 0xaf) return 3;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0xef:
|
|
|
|
/* c == 0xfeff */
|
|
|
|
if ((unsigned char)p[1] == 0xbb &&
|
|
|
|
(unsigned char)p[2] == 0xbf)
|
|
|
|
return 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#else /* !__APPLE__ */
|
2016-06-12 03:24:36 +03:00
|
|
|
# define NORMALIZE_UTF8PATH 0
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* __APPLE__ */
|
2013-08-08 05:26:27 +04:00
|
|
|
|
2016-04-11 00:54:41 +03:00
|
|
|
#define apply2args(n) (rb_check_arity(argc, n, UNLIMITED_ARGUMENTS), argc-=n)
|
|
|
|
|
2017-10-25 02:35:52 +03:00
|
|
|
struct apply_filename {
|
|
|
|
const char *ptr;
|
|
|
|
VALUE path;
|
|
|
|
};
|
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
struct apply_arg {
|
|
|
|
int i;
|
|
|
|
int argc;
|
|
|
|
int errnum;
|
|
|
|
int (*func)(const char *, void *);
|
|
|
|
void *arg;
|
2018-01-13 15:25:15 +03:00
|
|
|
struct apply_filename fn[FLEX_ARY_LEN];
|
2017-10-24 04:20:04 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static void *
|
|
|
|
no_gvl_apply2files(void *ptr)
|
|
|
|
{
|
|
|
|
struct apply_arg *aa = ptr;
|
|
|
|
|
|
|
|
for (aa->i = 0; aa->i < aa->argc; aa->i++) {
|
|
|
|
if (aa->func(aa->fn[aa->i].ptr, aa->arg) < 0) {
|
|
|
|
aa->errnum = errno;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef UTIME_EINVAL
|
|
|
|
NORETURN(static void utime_failed(struct apply_arg *));
|
|
|
|
static int utime_internal(const char *, void *);
|
|
|
|
#endif
|
|
|
|
|
2016-04-11 00:59:01 +03:00
|
|
|
static VALUE
|
2017-10-24 04:20:04 +03:00
|
|
|
apply2files(int (*func)(const char *, void *), int argc, VALUE *argv, void *arg)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-10-24 04:20:04 +03:00
|
|
|
VALUE v;
|
2017-10-25 02:35:52 +03:00
|
|
|
const size_t size = sizeof(struct apply_filename);
|
2018-01-14 14:19:18 +03:00
|
|
|
const long len = (long)(offsetof(struct apply_arg, fn) + (size * argc));
|
2017-10-24 04:20:04 +03:00
|
|
|
struct apply_arg *aa = ALLOCV(v, len);
|
|
|
|
|
|
|
|
aa->errnum = 0;
|
|
|
|
aa->argc = argc;
|
|
|
|
aa->arg = arg;
|
|
|
|
aa->func = func;
|
|
|
|
|
|
|
|
for (aa->i = 0; aa->i < argc; aa->i++) {
|
|
|
|
VALUE path = rb_get_path(argv[aa->i]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
path = rb_str_encode_ospath(path);
|
2017-10-24 04:20:04 +03:00
|
|
|
aa->fn[aa->i].ptr = RSTRING_PTR(path);
|
|
|
|
aa->fn[aa->i].path = path;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
rb_thread_call_without_gvl(no_gvl_apply2files, aa, RUBY_UBF_IO, 0);
|
|
|
|
if (aa->errnum) {
|
|
|
|
#ifdef UTIME_EINVAL
|
|
|
|
if (func == utime_internal) {
|
|
|
|
utime_failed(aa);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
rb_syserr_fail_path(aa->errnum, aa->fn[aa->i].path);
|
|
|
|
}
|
|
|
|
if (v) {
|
|
|
|
ALLOCV_END(v);
|
|
|
|
}
|
2016-04-11 00:59:01 +03:00
|
|
|
return LONG2FIX(argc);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-09-09 07:01:37 +04:00
|
|
|
static const rb_data_type_t stat_data_type = {
|
|
|
|
"stat",
|
2023-11-22 15:36:10 +03:00
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
RUBY_TYPED_DEFAULT_FREE,
|
|
|
|
NULL, // No external memory to report
|
|
|
|
},
|
|
|
|
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rb_stat {
|
|
|
|
struct stat stat;
|
|
|
|
bool initialized;
|
2009-09-09 07:01:37 +04:00
|
|
|
};
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2013-10-01 15:54:53 +04:00
|
|
|
stat_new_0(VALUE klass, const struct stat *st)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2023-11-22 15:36:10 +03:00
|
|
|
struct rb_stat *rb_st;
|
|
|
|
VALUE obj = TypedData_Make_Struct(klass, struct rb_stat, &stat_data_type, rb_st);
|
2001-10-03 11:19:19 +04:00
|
|
|
if (st) {
|
2023-11-22 15:36:10 +03:00
|
|
|
rb_st->stat = *st;
|
|
|
|
rb_st->initialized = true;
|
2001-10-03 11:19:19 +04:00
|
|
|
}
|
2015-05-16 15:56:29 +03:00
|
|
|
return obj;
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
|
|
|
|
2013-10-01 15:54:53 +04:00
|
|
|
VALUE
|
|
|
|
rb_stat_new(const struct stat *st)
|
2001-05-02 08:22:21 +04:00
|
|
|
{
|
|
|
|
return stat_new_0(rb_cStat, st);
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct stat*
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
get_stat(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2023-11-22 15:36:10 +03:00
|
|
|
struct rb_stat* rb_st;
|
|
|
|
TypedData_Get_Struct(self, struct rb_stat, &stat_data_type, rb_st);
|
|
|
|
if (!rb_st->initialized) rb_raise(rb_eTypeError, "uninitialized File::Stat");
|
|
|
|
return &rb_st->stat;
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2019-02-21 10:32:24 +03:00
|
|
|
static struct timespec stat_mtimespec(const struct stat *st);
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat <=> other_stat -> -1, 0, 1, nil
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2013-02-23 07:35:38 +04:00
|
|
|
* Compares File::Stat objects by comparing their respective modification
|
|
|
|
* times.
|
|
|
|
*
|
2014-01-09 21:33:47 +04:00
|
|
|
* +nil+ is returned if +other_stat+ is not a File::Stat object
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* f1 = File.new("f1", "w")
|
|
|
|
* sleep 1
|
|
|
|
* f2 = File.new("f2", "w")
|
|
|
|
* f1.stat <=> f2.stat #=> -1
|
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_cmp(VALUE self, VALUE other)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2001-10-29 08:07:26 +03:00
|
|
|
if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
struct timespec ts1 = stat_mtimespec(get_stat(self));
|
|
|
|
struct timespec ts2 = stat_mtimespec(get_stat(other));
|
|
|
|
if (ts1.tv_sec == ts2.tv_sec) {
|
|
|
|
if (ts1.tv_nsec == ts2.tv_nsec) return INT2FIX(0);
|
|
|
|
if (ts1.tv_nsec < ts2.tv_nsec) return INT2FIX(-1);
|
|
|
|
return INT2FIX(1);
|
|
|
|
}
|
|
|
|
if (ts1.tv_sec < ts2.tv_sec) return INT2FIX(-1);
|
|
|
|
return INT2FIX(1);
|
2001-10-29 08:07:26 +03:00
|
|
|
}
|
2002-11-22 12:14:24 +03:00
|
|
|
return Qnil;
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2008-08-05 09:19:45 +04:00
|
|
|
#define ST2UINT(val) ((val) & ~(~1UL << (sizeof(val) * CHAR_BIT - 1)))
|
|
|
|
|
2010-10-15 18:36:28 +04:00
|
|
|
#ifndef NUM2DEVT
|
|
|
|
# define NUM2DEVT(v) NUM2UINT(v)
|
|
|
|
#endif
|
|
|
|
#ifndef DEVT2NUM
|
|
|
|
# define DEVT2NUM(v) UINT2NUM(v)
|
|
|
|
#endif
|
|
|
|
#ifndef PRI_DEVT_PREFIX
|
|
|
|
# define PRI_DEVT_PREFIX ""
|
|
|
|
#endif
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.dev -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns an integer representing the device on which <i>stat</i>
|
|
|
|
* resides.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").dev #=> 774
|
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_dev(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2021-04-12 08:42:26 +03:00
|
|
|
#if SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_DEV_T
|
2010-10-14 03:09:56 +04:00
|
|
|
return DEVT2NUM(get_stat(self)->st_dev);
|
2021-04-12 08:42:26 +03:00
|
|
|
#elif SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_LONG
|
|
|
|
return ULONG2NUM(get_stat(self)->st_dev);
|
|
|
|
#else
|
|
|
|
return ULL2NUM(get_stat(self)->st_dev);
|
|
|
|
#endif
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2004-07-17 06:23:52 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.dev_major -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2004-07-17 06:23:52 +04:00
|
|
|
* Returns the major part of <code>File_Stat#dev</code> or
|
|
|
|
* <code>nil</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2004-07-17 06:23:52 +04:00
|
|
|
* File.stat("/dev/fd1").dev_major #=> 2
|
|
|
|
* File.stat("/dev/tty").dev_major #=> 5
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_dev_major(VALUE self)
|
2004-07-17 06:23:52 +04:00
|
|
|
{
|
|
|
|
#if defined(major)
|
2018-10-23 15:23:04 +03:00
|
|
|
return UINT2NUM(major(get_stat(self)->st_dev));
|
2004-07-17 06:23:52 +04:00
|
|
|
#else
|
|
|
|
return Qnil;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.dev_minor -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2004-07-17 06:23:52 +04:00
|
|
|
* Returns the minor part of <code>File_Stat#dev</code> or
|
|
|
|
* <code>nil</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2004-07-17 06:23:52 +04:00
|
|
|
* File.stat("/dev/fd1").dev_minor #=> 1
|
|
|
|
* File.stat("/dev/tty").dev_minor #=> 0
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_dev_minor(VALUE self)
|
2004-07-17 06:23:52 +04:00
|
|
|
{
|
|
|
|
#if defined(minor)
|
2018-10-23 15:23:04 +03:00
|
|
|
return UINT2NUM(minor(get_stat(self)->st_dev));
|
2004-07-17 06:23:52 +04:00
|
|
|
#else
|
|
|
|
return Qnil;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.ino -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the inode number for <i>stat</i>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").ino #=> 1083669
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_ino(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
support 128bit ino on Windows (if available)
* win32/win32.c, include/ruby/win32.h (stati128, rb_{,u,l,ul}stati128): rename
from stati64ns, change the type of st_ino to 64bit and added st_inohigh.
* dir.c, file.c (stat, lstat): follow above changes.
* file.c (rb_stat_ino): support 128bit ino.
* win32/win32.c (rb_{,u,l,ul}stati128): ditto.
[Feature #13731]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61096 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-12-10 20:26:58 +03:00
|
|
|
#ifdef HAVE_STRUCT_STAT_ST_INOHIGH
|
|
|
|
/* assume INTEGER_PACK_LSWORD_FIRST and st_inohigh is just next of st_ino */
|
|
|
|
return rb_integer_unpack(&get_stat(self)->st_ino, 2,
|
|
|
|
SIZEOF_STRUCT_STAT_ST_INO, 0,
|
|
|
|
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
|
|
|
|
INTEGER_PACK_2COMP);
|
2015-06-13 14:46:38 +03:00
|
|
|
#elif SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG
|
2003-08-15 07:01:52 +04:00
|
|
|
return ULL2NUM(get_stat(self)->st_ino);
|
|
|
|
#else
|
2001-05-02 08:22:21 +04:00
|
|
|
return ULONG2NUM(get_stat(self)->st_ino);
|
2003-08-15 07:01:52 +04:00
|
|
|
#endif
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.mode -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns an integer representing the permission bits of
|
|
|
|
* <i>stat</i>. The meaning of the bits is platform dependent; on
|
|
|
|
* Unix systems, see <code>stat(2)</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.chmod(0644, "testfile") #=> 1
|
|
|
|
* s = File.stat("testfile")
|
|
|
|
* sprintf("%o", s.mode) #=> "100644"
|
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_mode(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2008-08-05 09:19:45 +04:00
|
|
|
return UINT2NUM(ST2UINT(get_stat(self)->st_mode));
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.nlink -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the number of hard links to <i>stat</i>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").nlink #=> 1
|
|
|
|
* File.link("testfile", "testfile.bak") #=> 0
|
|
|
|
* File.stat("testfile").nlink #=> 2
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_nlink(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2020-04-08 07:28:13 +03:00
|
|
|
/* struct stat::st_nlink is nlink_t in POSIX. Not the case for Windows. */
|
|
|
|
const struct stat *ptr = get_stat(self);
|
|
|
|
|
|
|
|
if (sizeof(ptr->st_nlink) <= sizeof(int)) {
|
|
|
|
return UINT2NUM((unsigned)ptr->st_nlink);
|
|
|
|
}
|
|
|
|
else if (sizeof(ptr->st_nlink) == sizeof(long)) {
|
|
|
|
return ULONG2NUM((unsigned long)ptr->st_nlink);
|
|
|
|
}
|
|
|
|
else if (sizeof(ptr->st_nlink) == sizeof(LONG_LONG)) {
|
|
|
|
return ULL2NUM((unsigned LONG_LONG)ptr->st_nlink);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_bug(":FIXME: don't know what to do");
|
|
|
|
}
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.uid -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the numeric user id of the owner of <i>stat</i>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").uid #=> 501
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_uid(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2007-03-04 17:41:16 +03:00
|
|
|
return UIDT2NUM(get_stat(self)->st_uid);
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.gid -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the numeric group id of the owner of <i>stat</i>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").gid #=> 500
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_gid(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2007-03-04 17:41:16 +03:00
|
|
|
return GIDT2NUM(get_stat(self)->st_gid);
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.rdev -> integer or nil
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns an integer representing the device type on which
|
|
|
|
* <i>stat</i> resides. Returns <code>nil</code> if the operating
|
|
|
|
* system doesn't support this feature.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("/dev/fd1").rdev #=> 513
|
|
|
|
* File.stat("/dev/tty").rdev #=> 1280
|
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_rdev(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2013-05-09 16:12:17 +04:00
|
|
|
#ifdef HAVE_STRUCT_STAT_ST_RDEV
|
2021-04-12 08:42:26 +03:00
|
|
|
# if SIZEOF_STRUCT_STAT_ST_RDEV <= SIZEOF_DEV_T
|
2011-06-15 05:58:13 +04:00
|
|
|
return DEVT2NUM(get_stat(self)->st_rdev);
|
2021-04-12 08:42:26 +03:00
|
|
|
# elif SIZEOF_STRUCT_STAT_ST_RDEV <= SIZEOF_LONG
|
|
|
|
return ULONG2NUM(get_stat(self)->st_rdev);
|
|
|
|
# else
|
|
|
|
return ULL2NUM(get_stat(self)->st_rdev);
|
|
|
|
# endif
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
2002-08-12 11:39:12 +04:00
|
|
|
return Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.rdev_major -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the major part of <code>File_Stat#rdev</code> or
|
|
|
|
* <code>nil</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("/dev/fd1").rdev_major #=> 2
|
|
|
|
* File.stat("/dev/tty").rdev_major #=> 5
|
|
|
|
*/
|
|
|
|
|
2002-01-29 10:16:09 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_rdev_major(VALUE self)
|
2002-01-29 10:16:09 +03:00
|
|
|
{
|
2013-05-09 16:12:17 +04:00
|
|
|
#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major)
|
2018-10-23 15:23:04 +03:00
|
|
|
return UINT2NUM(major(get_stat(self)->st_rdev));
|
2002-01-29 10:16:09 +03:00
|
|
|
#else
|
2002-08-12 11:39:12 +04:00
|
|
|
return Qnil;
|
2002-01-29 10:16:09 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.rdev_minor -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the minor part of <code>File_Stat#rdev</code> or
|
|
|
|
* <code>nil</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("/dev/fd1").rdev_minor #=> 1
|
|
|
|
* File.stat("/dev/tty").rdev_minor #=> 0
|
|
|
|
*/
|
|
|
|
|
2002-01-29 10:16:09 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_rdev_minor(VALUE self)
|
2002-01-29 10:16:09 +03:00
|
|
|
{
|
2013-05-09 16:12:17 +04:00
|
|
|
#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor)
|
2018-10-23 15:23:04 +03:00
|
|
|
return UINT2NUM(minor(get_stat(self)->st_rdev));
|
2002-01-29 10:16:09 +03:00
|
|
|
#else
|
2002-08-12 11:39:12 +04:00
|
|
|
return Qnil;
|
2002-01-29 10:16:09 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.size -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the size of <i>stat</i> in bytes.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").size #=> 66
|
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_size(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2002-03-14 09:23:46 +03:00
|
|
|
return OFFT2NUM(get_stat(self)->st_size);
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.blksize -> integer or nil
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the native file system's block size. Will return <code>nil</code>
|
|
|
|
* on platforms that don't support this information.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").blksize #=> 4096
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_blksize(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2013-05-09 16:12:17 +04:00
|
|
|
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
2001-05-02 08:22:21 +04:00
|
|
|
return ULONG2NUM(get_stat(self)->st_blksize);
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
2002-08-12 11:39:12 +04:00
|
|
|
return Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.blocks -> integer or nil
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the number of native file system blocks allocated for this
|
2009-02-18 06:04:49 +03:00
|
|
|
* file, or <code>nil</code> if the operating system doesn't
|
2003-12-21 10:28:54 +03:00
|
|
|
* support this feature.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").blocks #=> 2
|
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_blocks(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
2009-03-11 23:27:07 +03:00
|
|
|
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
2009-03-19 12:49:51 +03:00
|
|
|
# if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
|
2009-03-11 23:27:07 +03:00
|
|
|
return ULL2NUM(get_stat(self)->st_blocks);
|
|
|
|
# else
|
2001-05-02 08:22:21 +04:00
|
|
|
return ULONG2NUM(get_stat(self)->st_blocks);
|
2009-03-11 23:27:07 +03:00
|
|
|
# endif
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
2002-08-12 11:39:12 +04:00
|
|
|
return Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
static struct timespec
|
2019-02-21 10:32:24 +03:00
|
|
|
stat_atimespec(const struct stat *st)
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
ts.tv_sec = st->st_atime;
|
|
|
|
#if defined(HAVE_STRUCT_STAT_ST_ATIM)
|
|
|
|
ts.tv_nsec = st->st_atim.tv_nsec;
|
|
|
|
#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
|
|
|
|
ts.tv_nsec = st->st_atimespec.tv_nsec;
|
|
|
|
#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
|
2014-10-11 17:33:14 +04:00
|
|
|
ts.tv_nsec = (long)st->st_atimensec;
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
#else
|
|
|
|
ts.tv_nsec = 0;
|
|
|
|
#endif
|
|
|
|
return ts;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2021-08-23 15:24:31 +03:00
|
|
|
stat_time(const struct timespec ts)
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
{
|
|
|
|
return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
|
|
|
|
}
|
|
|
|
|
2021-08-23 15:24:31 +03:00
|
|
|
static VALUE
|
|
|
|
stat_atime(const struct stat *st)
|
|
|
|
{
|
|
|
|
return stat_time(stat_atimespec(st));
|
|
|
|
}
|
|
|
|
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
static struct timespec
|
2019-02-21 10:32:24 +03:00
|
|
|
stat_mtimespec(const struct stat *st)
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
ts.tv_sec = st->st_mtime;
|
|
|
|
#if defined(HAVE_STRUCT_STAT_ST_MTIM)
|
|
|
|
ts.tv_nsec = st->st_mtim.tv_nsec;
|
|
|
|
#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
|
|
|
|
ts.tv_nsec = st->st_mtimespec.tv_nsec;
|
|
|
|
#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
|
2014-10-11 17:33:14 +04:00
|
|
|
ts.tv_nsec = (long)st->st_mtimensec;
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
#else
|
|
|
|
ts.tv_nsec = 0;
|
|
|
|
#endif
|
|
|
|
return ts;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2019-02-21 10:32:24 +03:00
|
|
|
stat_mtime(const struct stat *st)
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
{
|
2021-08-23 15:24:31 +03:00
|
|
|
return stat_time(stat_mtimespec(st));
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct timespec
|
2019-02-21 10:32:24 +03:00
|
|
|
stat_ctimespec(const struct stat *st)
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
ts.tv_sec = st->st_ctime;
|
|
|
|
#if defined(HAVE_STRUCT_STAT_ST_CTIM)
|
|
|
|
ts.tv_nsec = st->st_ctim.tv_nsec;
|
|
|
|
#elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
|
|
|
|
ts.tv_nsec = st->st_ctimespec.tv_nsec;
|
|
|
|
#elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
|
2014-10-11 17:33:14 +04:00
|
|
|
ts.tv_nsec = (long)st->st_ctimensec;
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
#else
|
|
|
|
ts.tv_nsec = 0;
|
|
|
|
#endif
|
|
|
|
return ts;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2019-02-21 10:32:24 +03:00
|
|
|
stat_ctime(const struct stat *st)
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
{
|
2021-08-23 15:24:31 +03:00
|
|
|
return stat_time(stat_ctimespec(st));
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
}
|
2003-12-21 10:28:54 +03:00
|
|
|
|
2014-05-22 15:49:22 +04:00
|
|
|
#define HAVE_STAT_BIRTHTIME
|
|
|
|
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
|
2019-02-22 06:08:38 +03:00
|
|
|
typedef struct stat statx_data;
|
2014-05-22 15:49:22 +04:00
|
|
|
static VALUE
|
2019-02-21 10:32:24 +03:00
|
|
|
stat_birthtime(const struct stat *st)
|
2014-05-22 15:49:22 +04:00
|
|
|
{
|
2019-02-21 10:32:24 +03:00
|
|
|
const struct timespec *ts = &st->st_birthtimespec;
|
2014-05-22 15:49:22 +04:00
|
|
|
return rb_time_nano_new(ts->tv_sec, ts->tv_nsec);
|
|
|
|
}
|
|
|
|
#elif defined(_WIN32)
|
2019-02-22 06:08:38 +03:00
|
|
|
typedef struct stat statx_data;
|
2014-05-22 18:34:54 +04:00
|
|
|
# define stat_birthtime stat_ctime
|
2014-05-22 15:49:22 +04:00
|
|
|
#else
|
|
|
|
# undef HAVE_STAT_BIRTHTIME
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) */
|
2014-05-22 15:49:22 +04:00
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.atime -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the last access time for this file as an object of class
|
2019-03-22 14:04:59 +03:00
|
|
|
* Time.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_atime(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_atime(get_stat(self));
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-04-18 11:53:05 +03:00
|
|
|
* stat.mtime -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the modification time of <i>stat</i>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_mtime(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_mtime(get_stat(self));
|
1999-12-01 12:24:48 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-04-18 11:53:05 +03:00
|
|
|
* stat.ctime -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the change time for <i>stat</i> (that is, the time
|
|
|
|
* directory information about the file was changed, not the file
|
|
|
|
* itself).
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2010-11-20 22:38:42 +03:00
|
|
|
* Note that on Windows (NTFS), returns creation time (birth time).
|
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_ctime(VALUE self)
|
1999-12-01 12:24:48 +03:00
|
|
|
{
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_ctime(get_stat(self));
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
2014-07-06 16:45:27 +04:00
|
|
|
#if defined(HAVE_STAT_BIRTHTIME)
|
2014-05-22 15:49:22 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-04-18 11:53:05 +03:00
|
|
|
* stat.birthtime -> time
|
2014-05-22 15:49:22 +04:00
|
|
|
*
|
|
|
|
* Returns the birth time for <i>stat</i>.
|
2015-01-21 03:44:06 +03:00
|
|
|
*
|
2015-01-19 20:57:03 +03:00
|
|
|
* If the platform doesn't have birthtime, raises NotImplementedError.
|
2014-05-22 15:49:22 +04:00
|
|
|
*
|
|
|
|
* File.write("testfile", "foo")
|
|
|
|
* sleep 10
|
|
|
|
* File.write("testfile", "bar")
|
|
|
|
* sleep 10
|
|
|
|
* File.chmod(0644, "testfile")
|
|
|
|
* sleep 10
|
|
|
|
* File.read("testfile")
|
|
|
|
* File.stat("testfile").birthtime #=> 2014-02-24 11:19:17 +0900
|
|
|
|
* File.stat("testfile").mtime #=> 2014-02-24 11:19:27 +0900
|
|
|
|
* File.stat("testfile").ctime #=> 2014-02-24 11:19:37 +0900
|
|
|
|
* File.stat("testfile").atime #=> 2014-02-24 11:19:47 +0900
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_stat_birthtime(VALUE self)
|
|
|
|
{
|
|
|
|
return stat_birthtime(get_stat(self));
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
# define rb_stat_birthtime rb_f_notimplement
|
|
|
|
#endif
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.inspect -> string
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
* array.c, enum.c, eval.c, file.c, io.c, numeric.c, object.c, prec.c,
process.c, re.c, string.c: typos in RDoc comments. [ruby-core:02783]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6158 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2004-04-14 08:06:52 +04:00
|
|
|
* Produce a nicely formatted description of <i>stat</i>.
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* File.stat("/etc/passwd").inspect
|
2009-02-18 06:04:49 +03:00
|
|
|
* #=> "#<File::Stat dev=0xe000005, ino=1078078, mode=0100644,
|
|
|
|
* # nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096,
|
|
|
|
* # blocks=8, atime=Wed Dec 10 10:16:12 CST 2003,
|
|
|
|
* # mtime=Fri Sep 12 15:41:41 CDT 2003,
|
2014-05-22 15:49:22 +04:00
|
|
|
* # ctime=Mon Oct 27 11:20:27 CST 2003,
|
|
|
|
* # birthtime=Mon Aug 04 08:13:49 CDT 2003>"
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2000-06-19 12:38:11 +04:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_inspect(VALUE self)
|
2000-06-19 12:38:11 +04:00
|
|
|
{
|
|
|
|
VALUE str;
|
2009-03-14 04:56:15 +03:00
|
|
|
size_t i;
|
2005-09-28 18:40:25 +04:00
|
|
|
static const struct {
|
|
|
|
const char *name;
|
2005-09-20 17:25:59 +04:00
|
|
|
VALUE (*func)(VALUE);
|
2000-06-19 12:38:11 +04:00
|
|
|
} member[] = {
|
2005-09-20 17:25:59 +04:00
|
|
|
{"dev", rb_stat_dev},
|
|
|
|
{"ino", rb_stat_ino},
|
|
|
|
{"mode", rb_stat_mode},
|
|
|
|
{"nlink", rb_stat_nlink},
|
|
|
|
{"uid", rb_stat_uid},
|
|
|
|
{"gid", rb_stat_gid},
|
|
|
|
{"rdev", rb_stat_rdev},
|
|
|
|
{"size", rb_stat_size},
|
|
|
|
{"blksize", rb_stat_blksize},
|
|
|
|
{"blocks", rb_stat_blocks},
|
|
|
|
{"atime", rb_stat_atime},
|
|
|
|
{"mtime", rb_stat_mtime},
|
|
|
|
{"ctime", rb_stat_ctime},
|
2014-05-22 15:49:22 +04:00
|
|
|
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
|
|
|
|
{"birthtime", rb_stat_birthtime},
|
|
|
|
#endif
|
2000-06-19 12:38:11 +04:00
|
|
|
};
|
|
|
|
|
2023-11-22 15:36:10 +03:00
|
|
|
struct rb_stat* rb_st;
|
|
|
|
TypedData_Get_Struct(self, struct rb_stat, &stat_data_type, rb_st);
|
|
|
|
if (!rb_st->initialized) {
|
2008-08-21 14:20:55 +04:00
|
|
|
return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
|
|
|
|
}
|
|
|
|
|
2001-05-30 13:12:34 +04:00
|
|
|
str = rb_str_buf_new2("#<");
|
2003-01-31 07:00:17 +03:00
|
|
|
rb_str_buf_cat2(str, rb_obj_classname(self));
|
2001-05-30 13:12:34 +04:00
|
|
|
rb_str_buf_cat2(str, " ");
|
2000-06-19 12:38:11 +04:00
|
|
|
|
|
|
|
for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
|
2002-01-29 10:16:09 +03:00
|
|
|
VALUE v;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2000-06-19 12:38:11 +04:00
|
|
|
if (i > 0) {
|
2001-05-30 13:12:34 +04:00
|
|
|
rb_str_buf_cat2(str, ", ");
|
2000-06-19 12:38:11 +04:00
|
|
|
}
|
2001-05-30 13:12:34 +04:00
|
|
|
rb_str_buf_cat2(str, member[i].name);
|
|
|
|
rb_str_buf_cat2(str, "=");
|
2002-01-29 10:16:09 +03:00
|
|
|
v = (*member[i].func)(self);
|
|
|
|
if (i == 2) { /* mode */
|
2010-10-15 15:30:33 +04:00
|
|
|
rb_str_catf(str, "0%lo", (unsigned long)NUM2ULONG(v));
|
2002-01-29 10:16:09 +03:00
|
|
|
}
|
2002-02-01 09:03:03 +03:00
|
|
|
else if (i == 0 || i == 6) { /* dev/rdev */
|
2010-10-15 15:30:33 +04:00
|
|
|
rb_str_catf(str, "0x%"PRI_DEVT_PREFIX"x", NUM2DEVT(v));
|
2002-02-01 09:03:03 +03:00
|
|
|
}
|
2002-01-29 10:16:09 +03:00
|
|
|
else {
|
|
|
|
rb_str_append(str, rb_inspect(v));
|
|
|
|
}
|
2000-06-19 12:38:11 +04:00
|
|
|
}
|
2001-05-30 13:12:34 +04:00
|
|
|
rb_str_buf_cat2(str, ">");
|
2000-06-19 12:38:11 +04:00
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2017-09-26 07:13:37 +03:00
|
|
|
typedef struct no_gvl_stat_data {
|
|
|
|
struct stat *st;
|
|
|
|
union {
|
|
|
|
const char *path;
|
|
|
|
int fd;
|
|
|
|
} file;
|
|
|
|
} no_gvl_stat_data;
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
no_gvl_fstat(void *data)
|
|
|
|
{
|
|
|
|
no_gvl_stat_data *arg = data;
|
|
|
|
return (VALUE)fstat(arg->file.fd, arg->st);
|
|
|
|
}
|
|
|
|
|
2018-02-28 08:17:01 +03:00
|
|
|
static int
|
|
|
|
fstat_without_gvl(int fd, struct stat *st)
|
|
|
|
{
|
|
|
|
no_gvl_stat_data data;
|
|
|
|
|
|
|
|
data.file.fd = fd;
|
|
|
|
data.st = st;
|
|
|
|
|
|
|
|
return (int)(VALUE)rb_thread_io_blocking_region(no_gvl_fstat, &data, fd);
|
|
|
|
}
|
|
|
|
|
2017-09-26 07:13:37 +03:00
|
|
|
static void *
|
|
|
|
no_gvl_stat(void * data)
|
|
|
|
{
|
|
|
|
no_gvl_stat_data *arg = data;
|
|
|
|
return (void *)(VALUE)STAT(arg->file.path, arg->st);
|
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
static int
|
2018-02-28 08:17:01 +03:00
|
|
|
stat_without_gvl(const char *path, struct stat *st)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2017-09-26 07:13:37 +03:00
|
|
|
no_gvl_stat_data data;
|
2003-04-14 13:04:43 +04:00
|
|
|
|
2018-02-28 08:17:01 +03:00
|
|
|
data.file.path = path;
|
2017-09-26 07:13:37 +03:00
|
|
|
data.st = st;
|
2018-02-28 08:17:01 +03:00
|
|
|
|
|
|
|
return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_stat, &data,
|
|
|
|
RUBY_UBF_IO, NULL);
|
|
|
|
}
|
|
|
|
|
2019-02-24 14:57:18 +03:00
|
|
|
#if !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
|
|
|
|
defined(HAVE_STRUCT_STATX_STX_BTIME)
|
2019-02-20 09:54:23 +03:00
|
|
|
|
2019-02-24 14:57:18 +03:00
|
|
|
# ifndef HAVE_STATX
|
2019-02-20 09:54:23 +03:00
|
|
|
# ifdef HAVE_SYSCALL_H
|
|
|
|
# include <syscall.h>
|
|
|
|
# elif defined HAVE_SYS_SYSCALL_H
|
|
|
|
# include <sys/syscall.h>
|
|
|
|
# endif
|
|
|
|
# if defined __linux__
|
|
|
|
# include <linux/stat.h>
|
|
|
|
static inline int
|
|
|
|
statx(int dirfd, const char *pathname, int flags,
|
|
|
|
unsigned int mask, struct statx *statxbuf)
|
|
|
|
{
|
2019-02-20 10:34:05 +03:00
|
|
|
return (int)syscall(__NR_statx, dirfd, pathname, flags, mask, statxbuf);
|
2019-02-20 09:54:23 +03:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif /* __linux__ */
|
|
|
|
# endif /* HAVE_STATX */
|
2019-02-20 09:54:23 +03:00
|
|
|
|
2019-02-19 08:44:53 +03:00
|
|
|
typedef struct no_gvl_statx_data {
|
|
|
|
struct statx *stx;
|
|
|
|
int fd;
|
|
|
|
const char *path;
|
|
|
|
int flags;
|
|
|
|
unsigned int mask;
|
|
|
|
} no_gvl_statx_data;
|
|
|
|
|
|
|
|
static VALUE
|
2019-02-21 09:12:13 +03:00
|
|
|
io_blocking_statx(void *data)
|
2019-02-19 08:44:53 +03:00
|
|
|
{
|
|
|
|
no_gvl_statx_data *arg = data;
|
|
|
|
return (VALUE)statx(arg->fd, arg->path, arg->flags, arg->mask, arg->stx);
|
|
|
|
}
|
|
|
|
|
2019-02-21 09:12:13 +03:00
|
|
|
static void *
|
|
|
|
no_gvl_statx(void *data)
|
|
|
|
{
|
|
|
|
return (void *)io_blocking_statx(data);
|
|
|
|
}
|
|
|
|
|
2019-02-19 08:44:53 +03:00
|
|
|
static int
|
2019-02-21 09:12:13 +03:00
|
|
|
statx_without_gvl(const char *path, struct statx *stx, unsigned int mask)
|
2019-02-19 08:44:53 +03:00
|
|
|
{
|
2019-02-21 09:12:13 +03:00
|
|
|
no_gvl_statx_data data = {stx, AT_FDCWD, path, 0, mask};
|
|
|
|
|
|
|
|
/* call statx(2) with pathname */
|
|
|
|
return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_statx, &data,
|
|
|
|
RUBY_UBF_IO, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fstatx_without_gvl(int fd, struct statx *stx, unsigned int mask)
|
|
|
|
{
|
2019-02-21 10:03:12 +03:00
|
|
|
no_gvl_statx_data data = {stx, fd, "", AT_EMPTY_PATH, mask};
|
2019-02-21 09:12:13 +03:00
|
|
|
|
|
|
|
/* call statx(2) with fd */
|
|
|
|
return (int)rb_thread_io_blocking_region(io_blocking_statx, &data, fd);
|
2019-02-19 08:44:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rb_statx(VALUE file, struct statx *stx, unsigned int mask)
|
|
|
|
{
|
|
|
|
VALUE tmp;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
tmp = rb_check_convert_type_with_id(file, T_FILE, "IO", idTo_io);
|
|
|
|
if (!NIL_P(tmp)) {
|
|
|
|
rb_io_t *fptr;
|
|
|
|
GetOpenFile(tmp, fptr);
|
2019-02-21 09:12:13 +03:00
|
|
|
result = fstatx_without_gvl(fptr->fd, stx, mask);
|
2019-02-19 08:44:53 +03:00
|
|
|
file = tmp;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
FilePathValue(file);
|
|
|
|
file = rb_str_encode_ospath(file);
|
2019-02-21 09:12:13 +03:00
|
|
|
result = statx_without_gvl(RSTRING_PTR(file), stx, mask);
|
2019-02-19 08:44:53 +03:00
|
|
|
}
|
|
|
|
RB_GC_GUARD(file);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-22 06:08:38 +03:00
|
|
|
# define statx_has_birthtime(st) ((st)->stx_mask & STATX_BTIME)
|
|
|
|
|
2019-07-20 09:42:59 +03:00
|
|
|
NORETURN(static void statx_notimplement(const char *field_name));
|
|
|
|
|
2019-03-23 13:41:16 +03:00
|
|
|
/* rb_notimplement() shows "function is unimplemented on this machine".
|
|
|
|
It is not applicable to statx which behavior depends on the filesystem. */
|
|
|
|
static void
|
|
|
|
statx_notimplement(const char *field_name)
|
|
|
|
{
|
|
|
|
rb_raise(rb_eNotImpError,
|
|
|
|
"%s is unimplemented on this filesystem",
|
|
|
|
field_name);
|
|
|
|
}
|
|
|
|
|
2019-02-19 08:44:53 +03:00
|
|
|
static VALUE
|
2019-02-22 06:08:38 +03:00
|
|
|
statx_birthtime(const struct statx *stx, VALUE fname)
|
2019-02-19 08:44:53 +03:00
|
|
|
{
|
2019-02-22 06:08:38 +03:00
|
|
|
if (!statx_has_birthtime(stx)) {
|
|
|
|
/* birthtime is not supported on the filesystem */
|
2019-03-23 13:41:16 +03:00
|
|
|
statx_notimplement("birthtime");
|
2019-02-22 06:08:38 +03:00
|
|
|
}
|
2021-03-14 14:10:01 +03:00
|
|
|
return rb_time_nano_new((time_t)stx->stx_btime.tv_sec, stx->stx_btime.tv_nsec);
|
2019-02-19 08:44:53 +03:00
|
|
|
}
|
2019-02-22 06:08:38 +03:00
|
|
|
|
|
|
|
typedef struct statx statx_data;
|
2019-02-22 09:01:08 +03:00
|
|
|
# define HAVE_STAT_BIRTHTIME
|
|
|
|
|
2019-02-22 06:08:38 +03:00
|
|
|
#elif defined(HAVE_STAT_BIRTHTIME)
|
|
|
|
# define statx_without_gvl(path, st, mask) stat_without_gvl(path, st)
|
|
|
|
# define fstatx_without_gvl(fd, st, mask) fstat_without_gvl(fd, st)
|
|
|
|
# define statx_birthtime(st, fname) stat_birthtime(st)
|
|
|
|
# define statx_has_birthtime(st) 1
|
|
|
|
# define rb_statx(file, st, mask) rb_stat(file, st)
|
|
|
|
#else
|
|
|
|
# define statx_has_birthtime(st) 0
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
|
2023-01-31 02:43:40 +03:00
|
|
|
defined(HAVE_STRUCT_STATX_STX_BTIME) */
|
2019-02-19 08:44:53 +03:00
|
|
|
|
2018-02-28 08:17:01 +03:00
|
|
|
static int
|
|
|
|
rb_stat(VALUE file, struct stat *st)
|
|
|
|
{
|
|
|
|
VALUE tmp;
|
|
|
|
int result;
|
|
|
|
|
2017-05-31 15:30:57 +03:00
|
|
|
tmp = rb_check_convert_type_with_id(file, T_FILE, "IO", idTo_io);
|
2003-04-14 13:04:43 +04:00
|
|
|
if (!NIL_P(tmp)) {
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2003-04-14 13:04:43 +04:00
|
|
|
GetOpenFile(tmp, fptr);
|
2018-02-28 08:17:01 +03:00
|
|
|
result = fstat_without_gvl(fptr->fd, st);
|
|
|
|
file = tmp;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
FilePathValue(file);
|
|
|
|
file = rb_str_encode_ospath(file);
|
|
|
|
result = stat_without_gvl(RSTRING_PTR(file), st);
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
2018-02-28 08:17:01 +03:00
|
|
|
RB_GC_GUARD(file);
|
|
|
|
return result;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-04-27 00:49:28 +03:00
|
|
|
* File.stat(filepath) -> stat
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2022-04-27 00:49:28 +03:00
|
|
|
* Returns a File::Stat object for the file at +filepath+ (see File::Stat):
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2022-04-27 00:49:28 +03:00
|
|
|
* File.stat('t.txt').class # => File::Stat
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_stat(VALUE klass, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(fname);
|
2018-02-28 08:17:01 +03:00
|
|
|
fname = rb_str_encode_ospath(fname);
|
|
|
|
if (stat_without_gvl(RSTRING_PTR(fname), &st) < 0) {
|
2012-02-24 11:37:48 +04:00
|
|
|
rb_sys_fail_path(fname);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2013-10-01 15:54:53 +04:00
|
|
|
return rb_stat_new(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* ios.stat -> stat
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns status information for <em>ios</em> as an object of type
|
2019-03-22 14:04:59 +03:00
|
|
|
* File::Stat.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* f = File.new("testfile")
|
|
|
|
* s = f.stat
|
|
|
|
* "%o" % s.mode #=> "100644"
|
|
|
|
* s.blksize #=> 4096
|
|
|
|
* s.atime #=> Wed Apr 09 08:53:54 CDT 2003
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_io_stat(VALUE obj)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
1998-01-16 15:13:05 +03:00
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
GetOpenFile(obj, fptr);
|
* rubyio.h, intern.h, io.c, file.c, process.c, ext/socket/socket.c,
ext/pty/pty.c, ext/io/wait/wait.c, ext/openssl/ossl_ssl.c:
Use own buffering mechanism instead of stdio.
* io.c, ext/stringio/stringio.c, test/ruby/ut_eof.rb:
EOF flag removed.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7473 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2004-12-06 11:40:30 +03:00
|
|
|
if (fstat(fptr->fd, &st) == -1) {
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2013-10-01 15:54:53 +04:00
|
|
|
return rb_stat_new(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2017-10-04 02:47:53 +03:00
|
|
|
#ifdef HAVE_LSTAT
|
|
|
|
static void *
|
|
|
|
no_gvl_lstat(void *ptr)
|
|
|
|
{
|
|
|
|
no_gvl_stat_data *arg = ptr;
|
|
|
|
return (void *)(VALUE)lstat(arg->file.path, arg->st);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
lstat_without_gvl(const char *path, struct stat *st)
|
|
|
|
{
|
|
|
|
no_gvl_stat_data data;
|
|
|
|
|
|
|
|
data.file.path = path;
|
|
|
|
data.st = st;
|
|
|
|
|
|
|
|
return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_lstat, &data,
|
|
|
|
RUBY_UBF_IO, NULL);
|
|
|
|
}
|
|
|
|
#endif /* HAVE_LSTAT */
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-04-27 00:49:28 +03:00
|
|
|
* File.lstat(filepath) -> stat
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2022-04-27 00:49:28 +03:00
|
|
|
* Like File::stat, but does not follow the last symbolic link;
|
|
|
|
* instead, returns a File::Stat object for the link itself.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2022-04-27 00:49:28 +03:00
|
|
|
* File.symlink('t.txt', 'symlink')
|
|
|
|
* File.stat('symlink').size # => 47
|
|
|
|
* File.lstat('symlink').size # => 5
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_lstat(VALUE klass, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2000-09-21 13:31:00 +04:00
|
|
|
#ifdef HAVE_LSTAT
|
1998-01-16 15:13:05 +03:00
|
|
|
struct stat st;
|
|
|
|
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(fname);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
fname = rb_str_encode_ospath(fname);
|
2017-10-04 02:47:53 +03:00
|
|
|
if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) {
|
2012-02-24 11:37:48 +04:00
|
|
|
rb_sys_fail_path(fname);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2013-10-01 15:54:53 +04:00
|
|
|
return rb_stat_new(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
2001-05-02 08:22:21 +04:00
|
|
|
return rb_file_s_stat(klass, fname);
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-04-27 00:49:28 +03:00
|
|
|
* lstat -> stat
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2022-04-27 00:49:28 +03:00
|
|
|
* Like File#stat, but does not follow the last symbolic link;
|
|
|
|
* instead, returns a File::Stat object for the link itself:
|
|
|
|
*
|
|
|
|
* File.symlink('t.txt', 'symlink')
|
|
|
|
* f = File.new('symlink')
|
|
|
|
* f.stat.size # => 47
|
|
|
|
* f.lstat.size # => 11
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_lstat(VALUE obj)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2000-09-21 13:31:00 +04:00
|
|
|
#ifdef HAVE_LSTAT
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
1998-01-16 15:13:05 +03:00
|
|
|
struct stat st;
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
VALUE path;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
GetOpenFile(obj, fptr);
|
2008-08-23 04:47:54 +04:00
|
|
|
if (NIL_P(fptr->pathv)) return Qnil;
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
path = rb_str_encode_ospath(fptr->pathv);
|
2017-10-04 02:47:53 +03:00
|
|
|
if (lstat_without_gvl(RSTRING_PTR(path), &st) == -1) {
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2013-10-01 15:54:53 +04:00
|
|
|
return rb_stat_new(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
2000-09-21 13:31:00 +04:00
|
|
|
return rb_io_stat(obj);
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2010-02-16 15:00:24 +03:00
|
|
|
rb_group_member(GETGROUPS_T gid)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2014-10-11 17:33:14 +04:00
|
|
|
#if defined(_WIN32) || !defined(HAVE_GETGROUPS)
|
2013-02-21 08:40:58 +04:00
|
|
|
return FALSE;
|
|
|
|
#else
|
2011-04-11 16:18:32 +04:00
|
|
|
int rv = FALSE;
|
2021-10-11 17:35:26 +03:00
|
|
|
int groups;
|
2013-02-21 08:40:58 +04:00
|
|
|
VALUE v = 0;
|
|
|
|
GETGROUPS_T *gary;
|
2013-03-01 20:37:31 +04:00
|
|
|
int anum = -1;
|
2013-02-21 08:40:58 +04:00
|
|
|
|
2006-11-22 11:37:11 +03:00
|
|
|
if (getgid() == gid || getegid() == gid)
|
2009-07-18 12:05:32 +04:00
|
|
|
return TRUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2021-10-11 17:35:26 +03:00
|
|
|
groups = getgroups(0, NULL);
|
|
|
|
gary = ALLOCV_N(GETGROUPS_T, v, groups);
|
|
|
|
anum = getgroups(groups, gary);
|
2013-02-21 08:40:58 +04:00
|
|
|
while (--anum >= 0) {
|
|
|
|
if (gary[anum] == gid) {
|
|
|
|
rv = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (v)
|
|
|
|
ALLOCV_END(v);
|
|
|
|
|
2011-04-11 16:18:32 +04:00
|
|
|
return rv;
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* defined(_WIN32) || !defined(HAVE_GETGROUPS) */
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef S_IXUGO
|
|
|
|
# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
|
|
|
|
#endif
|
|
|
|
|
2006-08-17 14:15:55 +04:00
|
|
|
#if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
|
|
|
|
#define USE_GETEUID 1
|
|
|
|
#endif
|
|
|
|
|
2006-01-25 16:30:11 +03:00
|
|
|
#ifndef HAVE_EACCESS
|
1998-01-16 15:13:05 +03:00
|
|
|
int
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
eaccess(const char *path, int mode)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2006-08-17 14:15:55 +04:00
|
|
|
#ifdef USE_GETEUID
|
2001-08-23 10:02:15 +04:00
|
|
|
struct stat st;
|
2007-03-04 17:41:16 +03:00
|
|
|
rb_uid_t euid;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2013-02-21 08:41:11 +04:00
|
|
|
euid = geteuid();
|
|
|
|
|
|
|
|
/* no setuid nor setgid. run shortcut. */
|
|
|
|
if (getuid() == euid && getgid() == getegid())
|
|
|
|
return access(path, mode);
|
|
|
|
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
if (STAT(path, &st) < 0)
|
|
|
|
return -1;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-08-23 10:02:15 +04:00
|
|
|
if (euid == 0) {
|
|
|
|
/* Root can read or write any file. */
|
|
|
|
if (!(mode & X_OK))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Root can execute any file that has any one of the execute
|
|
|
|
bits set. */
|
|
|
|
if (st.st_mode & S_IXUGO)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return -1;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2001-08-23 10:02:15 +04:00
|
|
|
if (st.st_uid == euid) /* owner */
|
|
|
|
mode <<= 6;
|
2010-02-16 15:00:24 +03:00
|
|
|
else if (rb_group_member(st.st_gid))
|
2001-08-23 10:02:15 +04:00
|
|
|
mode <<= 3;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2010-01-25 12:47:11 +03:00
|
|
|
if ((int)(st.st_mode & mode) == mode) return 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-08-23 10:02:15 +04:00
|
|
|
return -1;
|
2001-05-30 13:12:34 +04:00
|
|
|
#else
|
2001-08-23 10:02:15 +04:00
|
|
|
return access(path, mode);
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* USE_GETEUID */
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* HAVE_EACCESS */
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2017-11-28 06:28:35 +03:00
|
|
|
struct access_arg {
|
|
|
|
const char *path;
|
|
|
|
int mode;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *
|
|
|
|
nogvl_eaccess(void *ptr)
|
|
|
|
{
|
|
|
|
struct access_arg *aa = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)eaccess(aa->path, aa->mode);
|
|
|
|
}
|
|
|
|
|
2017-11-24 07:49:05 +03:00
|
|
|
static int
|
|
|
|
rb_eaccess(VALUE fname, int mode)
|
|
|
|
{
|
2017-11-28 06:28:35 +03:00
|
|
|
struct access_arg aa;
|
|
|
|
|
|
|
|
FilePathValue(fname);
|
|
|
|
fname = rb_str_encode_ospath(fname);
|
|
|
|
aa.path = StringValueCStr(fname);
|
|
|
|
aa.mode = mode;
|
|
|
|
|
|
|
|
return (int)(VALUE)rb_thread_call_without_gvl(nogvl_eaccess, &aa,
|
|
|
|
RUBY_UBF_IO, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
nogvl_access(void *ptr)
|
|
|
|
{
|
|
|
|
struct access_arg *aa = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)access(aa->path, aa->mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rb_access(VALUE fname, int mode)
|
|
|
|
{
|
|
|
|
struct access_arg aa;
|
|
|
|
|
2017-11-24 07:49:05 +03:00
|
|
|
FilePathValue(fname);
|
|
|
|
fname = rb_str_encode_ospath(fname);
|
2017-11-28 06:28:35 +03:00
|
|
|
aa.path = StringValueCStr(fname);
|
|
|
|
aa.mode = mode;
|
|
|
|
|
|
|
|
return (int)(VALUE)rb_thread_call_without_gvl(nogvl_access, &aa,
|
|
|
|
RUBY_UBF_IO, 0);
|
2017-11-24 07:49:05 +03:00
|
|
|
}
|
2003-12-21 10:28:54 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Document-class: FileTest
|
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* FileTest implements file test operations similar to those used in
|
|
|
|
* File::Stat. It exists as a standalone module, and its methods are
|
|
|
|
* also insinuated into the File class. (Note that this is not done
|
|
|
|
* by inclusion: the interpreter cheats).
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2006-12-07 18:18:14 +03:00
|
|
|
/*
|
2003-12-21 10:28:54 +03:00
|
|
|
* call-seq:
|
2022-04-27 00:49:28 +03:00
|
|
|
* File.directory?(path) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2022-04-27 00:49:28 +03:00
|
|
|
* With string +object+ given, returns +true+ if +path+ is a string path
|
|
|
|
* leading to a directory, or to a symbolic link to a directory; +false+ otherwise:
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2022-04-27 00:49:28 +03:00
|
|
|
* File.directory?('.') # => true
|
|
|
|
* File.directory?('foo') # => false
|
|
|
|
* File.symlink('.', 'dirlink') # => 0
|
|
|
|
* File.directory?('dirlink') # => true
|
|
|
|
* File.symlink('t,txt', 'filelink') # => 0
|
|
|
|
* File.directory?('filelink') # => false
|
|
|
|
*
|
|
|
|
* Argument +path+ can be an IO object.
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2006-12-07 18:18:14 +03:00
|
|
|
VALUE
|
|
|
|
rb_file_directory_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
#ifndef S_ISDIR
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
|
|
|
if (S_ISDIR(st.st_mode)) return Qtrue;
|
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-05-05 23:02:54 +03:00
|
|
|
* File.pipe?(filepath) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2022-05-05 23:02:54 +03:00
|
|
|
* Returns +true+ if +filepath+ points to a pipe, +false+ otherwise:
|
|
|
|
*
|
|
|
|
* File.mkfifo('tmp/fifo')
|
|
|
|
* File.pipe?('tmp/fifo') # => true
|
|
|
|
* File.pipe?('t.txt') # => false
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_pipe_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
#ifdef S_IFIFO
|
|
|
|
# ifndef S_ISFIFO
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
1998-01-16 15:13:05 +03:00
|
|
|
# endif
|
|
|
|
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
|
|
|
if (S_ISFIFO(st.st_mode)) return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
#endif
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-05-05 23:02:54 +03:00
|
|
|
* File.symlink?(filepath) -> true or false
|
|
|
|
*
|
|
|
|
* Returns +true+ if +filepath+ points to a symbolic link, +false+ otherwise:
|
|
|
|
*
|
|
|
|
* symlink = File.symlink('t.txt', 'symlink')
|
|
|
|
* File.symlink?('symlink') # => true
|
|
|
|
* File.symlink?('t.txt') # => false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_symlink_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
#ifndef S_ISLNK
|
|
|
|
# ifdef _S_ISLNK
|
|
|
|
# define S_ISLNK(m) _S_ISLNK(m)
|
|
|
|
# else
|
|
|
|
# ifdef _S_IFLNK
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
|
1998-01-16 15:13:05 +03:00
|
|
|
# else
|
|
|
|
# ifdef S_IFLNK
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
1998-01-16 15:13:05 +03:00
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef S_ISLNK
|
|
|
|
struct stat st;
|
|
|
|
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(fname);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
fname = rb_str_encode_ospath(fname);
|
2017-10-04 02:47:53 +03:00
|
|
|
if (lstat_without_gvl(StringValueCStr(fname), &st) < 0) return Qfalse;
|
1999-01-20 07:59:39 +03:00
|
|
|
if (S_ISLNK(st.st_mode)) return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
1999-12-14 09:50:43 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-05-05 23:02:54 +03:00
|
|
|
* File.socket?(filepath) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2022-05-05 23:02:54 +03:00
|
|
|
* Returns +true+ if +filepath+ points to a socket, +false+ otherwise:
|
|
|
|
*
|
|
|
|
* require 'socket'
|
|
|
|
* File.socket?(Socket.new(:INET, :STREAM)) # => true
|
|
|
|
* File.socket?(File.new('t.txt')) # => false
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_socket_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
#ifndef S_ISSOCK
|
|
|
|
# ifdef _S_ISSOCK
|
|
|
|
# define S_ISSOCK(m) _S_ISSOCK(m)
|
|
|
|
# else
|
|
|
|
# ifdef _S_IFSOCK
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
|
1998-01-16 15:13:05 +03:00
|
|
|
# else
|
|
|
|
# ifdef S_IFSOCK
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
1998-01-16 15:13:05 +03:00
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef S_ISSOCK
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
|
|
|
if (S_ISSOCK(st.st_mode)) return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
2022-11-18 01:50:25 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-05-05 23:02:54 +03:00
|
|
|
* File.blockdev?(filepath) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2022-05-05 23:02:54 +03:00
|
|
|
* Returns +true+ if +filepath+ points to a block device, +false+ otherwise:
|
|
|
|
*
|
2022-05-06 12:13:22 +03:00
|
|
|
* File.blockdev?('/dev/sda1') # => true
|
|
|
|
* File.blockdev?(File.new('t.tmp')) # => false
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_blockdev_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
#ifndef S_ISBLK
|
|
|
|
# ifdef S_IFBLK
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
1998-01-16 15:13:05 +03:00
|
|
|
# else
|
|
|
|
# define S_ISBLK(m) (0) /* anytime false */
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef S_ISBLK
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
|
|
|
if (S_ISBLK(st.st_mode)) return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
#endif
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2022-05-05 23:02:54 +03:00
|
|
|
* File.chardev?(filepath) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2022-05-05 23:02:54 +03:00
|
|
|
* Returns +true+ if +filepath+ points to a character device, +false+ otherwise.
|
|
|
|
*
|
2023-09-27 10:18:05 +03:00
|
|
|
* File.chardev?($stdin) # => true
|
2022-05-05 23:02:54 +03:00
|
|
|
* File.chardev?('t.txt') # => false
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_chardev_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
#ifndef S_ISCHR
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
2000-02-01 06:12:21 +03:00
|
|
|
if (S_ISCHR(st.st_mode)) return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.exist?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Return <code>true</code> if the named file exists.
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
|
|
|
*
|
|
|
|
* "file exists" means that stat() or fstat() system call is successful.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_exist_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
|
|
|
return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.readable?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file is readable by the effective
|
2015-09-12 10:14:38 +03:00
|
|
|
* user and group id of this process. See eaccess(3).
|
2019-10-15 03:43:11 +03:00
|
|
|
*
|
|
|
|
* Note that some OS-level security features may cause this to return true
|
|
|
|
* even though the file is not readable by the effective user/group.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_readable_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2021-07-29 06:51:10 +03:00
|
|
|
return RBOOL(rb_eaccess(fname, R_OK) >= 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.readable_real?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file is readable by the real
|
2015-09-12 10:14:38 +03:00
|
|
|
* user and group id of this process. See access(3).
|
2019-10-15 03:43:11 +03:00
|
|
|
*
|
|
|
|
* Note that some OS-level security features may cause this to return true
|
|
|
|
* even though the file is not readable by the real user/group.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_readable_real_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2021-07-29 06:51:10 +03:00
|
|
|
return RBOOL(rb_access(fname, R_OK) >= 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2004-01-12 19:26:05 +03:00
|
|
|
#ifndef S_IRUGO
|
|
|
|
# define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef S_IWUGO
|
|
|
|
# define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
|
|
|
|
#endif
|
|
|
|
|
2004-01-12 16:34:26 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* File.world_readable?(file_name) -> integer or nil
|
2004-01-12 16:34:26 +03:00
|
|
|
*
|
|
|
|
* If <i>file_name</i> is readable by others, returns an integer
|
|
|
|
* representing the file permission bits of <i>file_name</i>. Returns
|
|
|
|
* <code>nil</code> otherwise. The meaning of the bits is platform
|
|
|
|
* dependent; on Unix systems, see <code>stat(2)</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2013-04-24 16:41:06 +04:00
|
|
|
* _file_name_ can be an IO object.
|
|
|
|
*
|
2010-05-18 01:07:33 +04:00
|
|
|
* File.world_readable?("/etc/passwd") #=> 420
|
2004-01-12 16:34:26 +03:00
|
|
|
* m = File.world_readable?("/etc/passwd")
|
2010-05-18 01:07:33 +04:00
|
|
|
* sprintf("%o", m) #=> "644"
|
2004-01-12 16:34:26 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_world_readable_p(VALUE obj, VALUE fname)
|
2004-01-12 16:34:26 +03:00
|
|
|
{
|
|
|
|
#ifdef S_IROTH
|
|
|
|
struct stat st;
|
|
|
|
|
2004-01-12 19:26:05 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qnil;
|
2004-01-12 16:34:26 +03:00
|
|
|
if ((st.st_mode & (S_IROTH)) == S_IROTH) {
|
2004-01-19 15:28:14 +03:00
|
|
|
return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
|
2004-01-12 16:34:26 +03:00
|
|
|
}
|
|
|
|
#endif
|
2004-01-12 19:26:05 +03:00
|
|
|
return Qnil;
|
2004-01-12 16:34:26 +03:00
|
|
|
}
|
2003-12-21 10:28:54 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.writable?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file is writable by the effective
|
2015-09-12 10:14:38 +03:00
|
|
|
* user and group id of this process. See eaccess(3).
|
2019-10-15 03:43:11 +03:00
|
|
|
*
|
|
|
|
* Note that some OS-level security features may cause this to return true
|
|
|
|
* even though the file is not writable by the effective user/group.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_writable_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2021-07-29 06:51:10 +03:00
|
|
|
return RBOOL(rb_eaccess(fname, W_OK) >= 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.writable_real?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file is writable by the real
|
2019-10-15 03:43:11 +03:00
|
|
|
* user and group id of this process. See access(3).
|
|
|
|
*
|
|
|
|
* Note that some OS-level security features may cause this to return true
|
|
|
|
* even though the file is not writable by the real user/group.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_writable_real_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2021-07-29 06:51:10 +03:00
|
|
|
return RBOOL(rb_access(fname, W_OK) >= 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2004-01-12 16:34:26 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* File.world_writable?(file_name) -> integer or nil
|
2004-01-12 16:34:26 +03:00
|
|
|
*
|
|
|
|
* If <i>file_name</i> is writable by others, returns an integer
|
|
|
|
* representing the file permission bits of <i>file_name</i>. Returns
|
|
|
|
* <code>nil</code> otherwise. The meaning of the bits is platform
|
|
|
|
* dependent; on Unix systems, see <code>stat(2)</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2013-04-24 16:41:06 +04:00
|
|
|
* _file_name_ can be an IO object.
|
|
|
|
*
|
2004-01-12 16:34:26 +03:00
|
|
|
* File.world_writable?("/tmp") #=> 511
|
|
|
|
* m = File.world_writable?("/tmp")
|
|
|
|
* sprintf("%o", m) #=> "777"
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_world_writable_p(VALUE obj, VALUE fname)
|
2004-01-12 16:34:26 +03:00
|
|
|
{
|
|
|
|
#ifdef S_IWOTH
|
|
|
|
struct stat st;
|
|
|
|
|
2008-11-22 12:28:43 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qnil;
|
2004-01-12 16:34:26 +03:00
|
|
|
if ((st.st_mode & (S_IWOTH)) == S_IWOTH) {
|
2004-01-19 15:28:14 +03:00
|
|
|
return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
|
2004-01-12 16:34:26 +03:00
|
|
|
}
|
|
|
|
#endif
|
2004-01-12 19:26:05 +03:00
|
|
|
return Qnil;
|
2004-01-12 16:34:26 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.executable?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file is executable by the effective
|
2015-09-12 10:14:38 +03:00
|
|
|
* user and group id of this process. See eaccess(3).
|
2019-06-11 22:05:04 +03:00
|
|
|
*
|
|
|
|
* Windows does not support execute permissions separately from read
|
|
|
|
* permissions. On Windows, a file is only considered executable if it ends in
|
|
|
|
* .bat, .cmd, .com, or .exe.
|
2019-10-15 03:43:11 +03:00
|
|
|
*
|
|
|
|
* Note that some OS-level security features may cause this to return true
|
|
|
|
* even though the file is not executable by the effective user/group.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_executable_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2021-07-29 06:51:10 +03:00
|
|
|
return RBOOL(rb_eaccess(fname, X_OK) >= 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.executable_real?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file is executable by the real
|
2015-09-12 10:14:38 +03:00
|
|
|
* user and group id of this process. See access(3).
|
2019-06-11 22:05:04 +03:00
|
|
|
*
|
|
|
|
* Windows does not support execute permissions separately from read
|
|
|
|
* permissions. On Windows, a file is only considered executable if it ends in
|
|
|
|
* .bat, .cmd, .com, or .exe.
|
2019-10-15 03:43:11 +03:00
|
|
|
*
|
|
|
|
* Note that some OS-level security features may cause this to return true
|
|
|
|
* even though the file is not executable by the real user/group.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_executable_real_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2021-07-29 06:51:10 +03:00
|
|
|
return RBOOL(rb_access(fname, X_OK) >= 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef S_ISREG
|
2010-12-13 06:01:12 +03:00
|
|
|
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2014-07-28 00:23:45 +04:00
|
|
|
* File.file?(file) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2014-07-28 00:23:45 +04:00
|
|
|
* Returns +true+ if the named +file+ exists and is a regular file.
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
2014-07-28 00:23:45 +04:00
|
|
|
* +file+ can be an IO object.
|
|
|
|
*
|
|
|
|
* If the +file+ argument is a symbolic link, it will resolve the symbolic link
|
|
|
|
* and use the file referenced by the link.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_file_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
2021-09-15 02:11:05 +03:00
|
|
|
return RBOOL(S_ISREG(st.st_mode));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.zero?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file exists and has
|
|
|
|
* a zero size.
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_zero_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
2021-09-15 02:11:05 +03:00
|
|
|
return RBOOL(st.st_size == 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.size?(file_name) -> Integer or nil
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2006-08-28 02:25:08 +04:00
|
|
|
* Returns +nil+ if +file_name+ doesn't exist or has zero size, the size of the
|
|
|
|
* file otherwise.
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_size_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qnil;
|
|
|
|
if (st.st_size == 0) return Qnil;
|
2002-03-14 09:23:46 +03:00
|
|
|
return OFFT2NUM(st.st_size);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.owned?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file exists and the
|
|
|
|
* effective used id of the calling process is the owner of
|
|
|
|
* the file.
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_owned_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
2021-09-15 02:11:05 +03:00
|
|
|
return RBOOL(st.st_uid == geteuid());
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_rowned_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
2021-09-15 02:11:05 +03:00
|
|
|
return RBOOL(st.st_uid == getuid());
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.grpowned?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named file exists and the
|
|
|
|
* effective group id of the calling process is the owner of
|
|
|
|
* the file. Returns <code>false</code> on Windows.
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_grpowned_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-15 06:18:08 +03:00
|
|
|
#ifndef _WIN32
|
1998-01-16 15:13:05 +03:00
|
|
|
struct stat st;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
2010-02-16 15:00:24 +03:00
|
|
|
if (rb_group_member(st.st_gid)) return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
|
|
|
|
static VALUE
|
2005-09-12 19:02:46 +04:00
|
|
|
check3rdbyte(VALUE fname, int mode)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
2017-10-04 02:47:29 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) return Qfalse;
|
2021-09-15 02:11:05 +03:00
|
|
|
return RBOOL(st.st_mode & mode);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.setuid?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2005-11-22 19:26:39 +03:00
|
|
|
* Returns <code>true</code> if the named file has the setuid bit set.
|
2018-10-20 14:47:45 +03:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_suid_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
#ifdef S_ISUID
|
2001-05-02 08:22:21 +04:00
|
|
|
return check3rdbyte(fname, S_ISUID);
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.setgid?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2005-11-22 19:26:39 +03:00
|
|
|
* Returns <code>true</code> if the named file has the setgid bit set.
|
2018-10-20 14:47:45 +03:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_sgid_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2000-05-13 20:13:31 +04:00
|
|
|
#ifdef S_ISGID
|
2001-05-02 08:22:21 +04:00
|
|
|
return check3rdbyte(fname, S_ISGID);
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.sticky?(file_name) -> true or false
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2005-11-22 19:26:39 +03:00
|
|
|
* Returns <code>true</code> if the named file has the sticky bit set.
|
2018-10-20 14:47:45 +03:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_sticky_p(VALUE obj, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
#ifdef S_ISVTX
|
2001-05-02 08:22:21 +04:00
|
|
|
return check3rdbyte(fname, S_ISVTX);
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
2022-04-15 10:40:25 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-11-22 19:26:39 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.identical?(file_1, file_2) -> true or false
|
2005-11-22 19:26:39 +03:00
|
|
|
*
|
|
|
|
* Returns <code>true</code> if the named files are identical.
|
2005-12-21 12:20:15 +03:00
|
|
|
*
|
2013-04-24 16:41:06 +04:00
|
|
|
* _file_1_ and _file_2_ can be an IO object.
|
|
|
|
*
|
2005-12-21 12:20:15 +03:00
|
|
|
* open("a", "w") {}
|
|
|
|
* p File.identical?("a", "a") #=> true
|
|
|
|
* p File.identical?("a", "./a") #=> true
|
|
|
|
* File.link("a", "b")
|
|
|
|
* p File.identical?("a", "b") #=> true
|
|
|
|
* File.symlink("a", "c")
|
|
|
|
* p File.identical?("a", "c") #=> true
|
|
|
|
* open("d", "w") {}
|
|
|
|
* p File.identical?("a", "d") #=> false
|
2005-11-22 19:26:39 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2006-12-07 18:18:14 +03:00
|
|
|
rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
|
2005-11-22 19:26:39 +03:00
|
|
|
{
|
2015-10-18 04:19:13 +03:00
|
|
|
#ifndef _WIN32
|
2005-11-22 19:26:39 +03:00
|
|
|
struct stat st1, st2;
|
|
|
|
|
|
|
|
if (rb_stat(fname1, &st1) < 0) return Qfalse;
|
|
|
|
if (rb_stat(fname2, &st2) < 0) return Qfalse;
|
|
|
|
if (st1.st_dev != st2.st_dev) return Qfalse;
|
|
|
|
if (st1.st_ino != st2.st_ino) return Qfalse;
|
2015-10-18 19:29:07 +03:00
|
|
|
return Qtrue;
|
2005-11-22 19:26:39 +03:00
|
|
|
#else
|
2017-12-04 06:33:48 +03:00
|
|
|
extern VALUE rb_w32_file_identical_p(VALUE, VALUE);
|
|
|
|
return rb_w32_file_identical_p(fname1, fname2);
|
2005-11-22 19:26:39 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.size(file_name) -> integer
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Returns the size of <code>file_name</code>.
|
2013-04-24 16:41:06 +04:00
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_size(VALUE klass, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
2009-01-05 02:59:20 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
2009-01-05 02:59:20 +03:00
|
|
|
FilePathValue(fname);
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, fname);
|
2009-01-05 02:59:20 +03:00
|
|
|
}
|
2002-08-28 12:05:23 +04:00
|
|
|
return OFFT2NUM(st.st_size);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2005-09-12 19:02:46 +04:00
|
|
|
rb_file_ftype(const struct stat *st)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2006-06-20 22:02:17 +04:00
|
|
|
const char *t;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-12-07 12:25:55 +03:00
|
|
|
if (S_ISREG(st->st_mode)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
t = "file";
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
|
|
|
else if (S_ISDIR(st->st_mode)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
t = "directory";
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
|
|
|
else if (S_ISCHR(st->st_mode)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
t = "characterSpecial";
|
|
|
|
}
|
|
|
|
#ifdef S_ISBLK
|
1999-12-07 12:25:55 +03:00
|
|
|
else if (S_ISBLK(st->st_mode)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
t = "blockSpecial";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef S_ISFIFO
|
1999-12-07 12:25:55 +03:00
|
|
|
else if (S_ISFIFO(st->st_mode)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
t = "fifo";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef S_ISLNK
|
1999-12-07 12:25:55 +03:00
|
|
|
else if (S_ISLNK(st->st_mode)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
t = "link";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef S_ISSOCK
|
1999-12-07 12:25:55 +03:00
|
|
|
else if (S_ISSOCK(st->st_mode)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
t = "socket";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else {
|
|
|
|
t = "unknown";
|
|
|
|
}
|
|
|
|
|
* string.c (rb_str_usascii_new{,2}: defined.
(rb_str_new): set US-ASCII and ENC_CODERANGE_7BIT when empty
string.
* encoding.c (rb_usascii_encoding, rb_usascii_encindex): defined.
(rb_enc_inspect, enc_name, rb_locale_charmap, rb_enc_name_list_i):
use rb_str_ascii_new.
* array.c (recursive_join, inspect_ary): ditto.
* object.c (nil_to_s, nil_inspect, true_to_s, false_to_s,
rb_mod_to_s): ditto.
* hash.c (inspect_hash, rb_hash_inspect, rb_f_getenv, env_fetch,
env_clear, env_to_s, env_inspect): ditto.
* numeric.c (flo_to_s, int_chr, rb_fix2str): ditto.
* bignum.c (rb_big2str): ditto.
* file.c (rb_file_ftype, rb_file_s_dirname, rb_file_s_extname,
file_inspect_join, Init_file): ditto.
* test/ruby/test_ruby_m17n.rb: add checks for encoding of string.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15244 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-01-25 19:40:02 +03:00
|
|
|
return rb_usascii_str_new2(t);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.ftype(file_name) -> string
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Identifies the type of the named file; the return string is one of
|
|
|
|
* ``<code>file</code>'', ``<code>directory</code>'',
|
|
|
|
* ``<code>characterSpecial</code>'', ``<code>blockSpecial</code>'',
|
|
|
|
* ``<code>fifo</code>'', ``<code>link</code>'',
|
|
|
|
* ``<code>socket</code>'', or ``<code>unknown</code>''.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.ftype("testfile") #=> "file"
|
|
|
|
* File.ftype("/dev/tty") #=> "characterSpecial"
|
|
|
|
* File.ftype("/tmp/.X11-unix/X0") #=> "socket"
|
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_ftype(VALUE klass, VALUE fname)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(fname);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
fname = rb_str_encode_ospath(fname);
|
2017-10-04 02:47:53 +03:00
|
|
|
if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) {
|
2012-02-24 11:37:48 +04:00
|
|
|
rb_sys_fail_path(fname);
|
1999-11-25 12:03:08 +03:00
|
|
|
}
|
|
|
|
|
1999-12-07 12:25:55 +03:00
|
|
|
return rb_file_ftype(&st);
|
1999-11-25 12:03:08 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.atime(file_name) -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2017-12-22 06:35:46 +03:00
|
|
|
* Returns the last access time for the named file as a Time object.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2013-04-24 16:41:06 +04:00
|
|
|
* _file_name_ can be an IO object.
|
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.atime("testfile") #=> Wed Apr 09 08:51:48 CDT 2003
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_atime(VALUE klass, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
2009-01-05 02:59:20 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
2009-01-05 02:59:20 +03:00
|
|
|
FilePathValue(fname);
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, fname);
|
2009-01-05 02:59:20 +03:00
|
|
|
}
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_atime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* file.atime -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* Returns the last access time (a Time object) for <i>file</i>, or
|
|
|
|
* epoch if <i>file</i> has not been accessed.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.new("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_atime(VALUE obj)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
1998-01-16 15:13:05 +03:00
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
GetOpenFile(obj, fptr);
|
* rubyio.h, intern.h, io.c, file.c, process.c, ext/socket/socket.c,
ext/pty/pty.c, ext/io/wait/wait.c, ext/openssl/ossl_ssl.c:
Use own buffering mechanism instead of stdio.
* io.c, ext/stringio/stringio.c, test/ruby/ut_eof.rb:
EOF flag removed.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7473 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2004-12-06 11:40:30 +03:00
|
|
|
if (fstat(fptr->fd, &st) == -1) {
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_atime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.mtime(file_name) -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the modification time for the named file as a Time object.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2013-04-24 16:41:06 +04:00
|
|
|
* _file_name_ can be an IO object.
|
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.mtime("testfile") #=> Tue Apr 08 12:58:04 CDT 2003
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_mtime(VALUE klass, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
2009-01-05 02:59:20 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
2009-01-05 02:59:20 +03:00
|
|
|
FilePathValue(fname);
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, fname);
|
2009-01-05 02:59:20 +03:00
|
|
|
}
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_mtime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* file.mtime -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the modification time for <i>file</i>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.new("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_mtime(VALUE obj)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
1998-01-16 15:13:05 +03:00
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
GetOpenFile(obj, fptr);
|
* rubyio.h, intern.h, io.c, file.c, process.c, ext/socket/socket.c,
ext/pty/pty.c, ext/io/wait/wait.c, ext/openssl/ossl_ssl.c:
Use own buffering mechanism instead of stdio.
* io.c, ext/stringio/stringio.c, test/ruby/ut_eof.rb:
EOF flag removed.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7473 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2004-12-06 11:40:30 +03:00
|
|
|
if (fstat(fptr->fd, &st) == -1) {
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_mtime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.ctime(file_name) -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the change time for the named file (the time at which
|
|
|
|
* directory information about the file was changed, not the file
|
|
|
|
* itself).
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2013-04-24 16:41:06 +04:00
|
|
|
* _file_name_ can be an IO object.
|
|
|
|
*
|
2010-12-06 13:01:48 +03:00
|
|
|
* Note that on Windows (NTFS), returns creation time (birth time).
|
2010-11-20 22:38:42 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.ctime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_ctime(VALUE klass, VALUE fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
2009-01-05 02:59:20 +03:00
|
|
|
if (rb_stat(fname, &st) < 0) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
2009-01-05 02:59:20 +03:00
|
|
|
FilePathValue(fname);
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, fname);
|
2009-01-05 02:59:20 +03:00
|
|
|
}
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_ctime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* file.ctime -> time
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the change time for <i>file</i> (that is, the time directory
|
|
|
|
* information about the file was changed, not the file itself).
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2010-12-06 13:01:48 +03:00
|
|
|
* Note that on Windows (NTFS), returns creation time (birth time).
|
2010-11-20 22:38:42 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.new("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_ctime(VALUE obj)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
1998-01-16 15:13:05 +03:00
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
GetOpenFile(obj, fptr);
|
* rubyio.h, intern.h, io.c, file.c, process.c, ext/socket/socket.c,
ext/pty/pty.c, ext/io/wait/wait.c, ext/openssl/ossl_ssl.c:
Use own buffering mechanism instead of stdio.
* io.c, ext/stringio/stringio.c, test/ruby/ut_eof.rb:
EOF flag removed.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7473 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2004-12-06 11:40:30 +03:00
|
|
|
if (fstat(fptr->fd, &st) == -1) {
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_ctime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2023-12-06 13:56:38 +03:00
|
|
|
#if defined(HAVE_STAT_BIRTHTIME)
|
2014-05-22 15:49:22 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* File.birthtime(file_name) -> time
|
|
|
|
*
|
|
|
|
* Returns the birth time for the named file.
|
|
|
|
*
|
|
|
|
* _file_name_ can be an IO object.
|
|
|
|
*
|
|
|
|
* File.birthtime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
|
|
|
|
*
|
2015-01-21 03:44:06 +03:00
|
|
|
* If the platform doesn't have birthtime, raises NotImplementedError.
|
|
|
|
*
|
2014-05-22 15:49:22 +04:00
|
|
|
*/
|
|
|
|
|
2019-02-20 09:54:23 +03:00
|
|
|
RUBY_FUNC_EXPORTED VALUE
|
2014-05-22 15:49:22 +04:00
|
|
|
rb_file_s_birthtime(VALUE klass, VALUE fname)
|
|
|
|
{
|
2019-02-22 06:08:38 +03:00
|
|
|
statx_data st;
|
2014-05-22 15:49:22 +04:00
|
|
|
|
2019-02-22 06:08:38 +03:00
|
|
|
if (rb_statx(fname, &st, STATX_BTIME) < 0) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
2014-05-22 15:49:22 +04:00
|
|
|
FilePathValue(fname);
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, fname);
|
2014-05-22 15:49:22 +04:00
|
|
|
}
|
2019-02-22 06:08:38 +03:00
|
|
|
return statx_birthtime(&st, fname);
|
2014-05-22 15:49:22 +04:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
# define rb_file_s_birthtime rb_f_notimplement
|
|
|
|
#endif
|
|
|
|
|
2014-07-06 16:45:27 +04:00
|
|
|
#if defined(HAVE_STAT_BIRTHTIME)
|
2014-05-22 15:49:22 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* file.birthtime -> time
|
|
|
|
*
|
|
|
|
* Returns the birth time for <i>file</i>.
|
|
|
|
*
|
|
|
|
* File.new("testfile").birthtime #=> Wed Apr 09 08:53:14 CDT 2003
|
|
|
|
*
|
2015-01-21 03:44:06 +03:00
|
|
|
* If the platform doesn't have birthtime, raises NotImplementedError.
|
|
|
|
*
|
2014-05-22 15:49:22 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_file_birthtime(VALUE obj)
|
|
|
|
{
|
|
|
|
rb_io_t *fptr;
|
2019-02-22 09:01:08 +03:00
|
|
|
statx_data st;
|
2014-05-22 15:49:22 +04:00
|
|
|
|
|
|
|
GetOpenFile(obj, fptr);
|
2019-02-22 09:01:08 +03:00
|
|
|
if (fstatx_without_gvl(fptr->fd, &st, STATX_BTIME) == -1) {
|
2014-05-22 15:49:22 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
|
|
|
}
|
2019-02-22 09:01:08 +03:00
|
|
|
return statx_birthtime(&st, fptr->pathv);
|
2014-05-22 15:49:22 +04:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
# define rb_file_birthtime rb_f_notimplement
|
|
|
|
#endif
|
|
|
|
|
2022-09-05 14:23:27 +03:00
|
|
|
rb_off_t
|
2021-11-10 10:41:26 +03:00
|
|
|
rb_file_size(VALUE file)
|
2009-02-24 18:45:16 +03:00
|
|
|
{
|
2021-12-19 23:59:45 +03:00
|
|
|
if (RB_TYPE_P(file, T_FILE)) {
|
|
|
|
rb_io_t *fptr;
|
|
|
|
struct stat st;
|
2009-02-24 18:45:16 +03:00
|
|
|
|
2021-12-19 23:59:45 +03:00
|
|
|
RB_IO_POINTER(file, fptr);
|
|
|
|
if (fptr->mode & FMODE_WRITABLE) {
|
|
|
|
rb_io_flush_raw(file, 0);
|
|
|
|
}
|
2021-07-02 13:41:16 +03:00
|
|
|
|
2021-12-19 23:59:45 +03:00
|
|
|
if (fstat(fptr->fd, &st) == -1) {
|
|
|
|
rb_sys_fail_path(fptr->pathv);
|
|
|
|
}
|
2021-07-02 13:41:16 +03:00
|
|
|
|
2021-12-19 23:59:45 +03:00
|
|
|
return st.st_size;
|
2021-12-24 13:52:44 +03:00
|
|
|
}
|
|
|
|
else {
|
2021-12-19 23:59:45 +03:00
|
|
|
return NUM2OFFT(rb_funcall(file, idSize, 0));
|
|
|
|
}
|
2021-07-02 13:41:16 +03:00
|
|
|
}
|
|
|
|
|
2023-12-06 13:56:38 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* file.size -> integer
|
|
|
|
*
|
|
|
|
* Returns the size of <i>file</i> in bytes.
|
|
|
|
*
|
|
|
|
* File.new("testfile").size #=> 66
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-07-02 13:41:16 +03:00
|
|
|
static VALUE
|
|
|
|
file_size(VALUE self)
|
|
|
|
{
|
2021-11-10 10:41:26 +03:00
|
|
|
return OFFT2NUM(rb_file_size(self));
|
2009-02-24 18:45:16 +03:00
|
|
|
}
|
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
static int
|
|
|
|
chmod_internal(const char *path, void *mode)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-10-31 22:10:19 +03:00
|
|
|
return chmod(path, *(mode_t *)mode);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.chmod(mode_int, file_name, ... ) -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Changes permission bits on the named file(s) to the bit pattern
|
|
|
|
* represented by <i>mode_int</i>. Actual effects are operating system
|
|
|
|
* dependent (see the beginning of this section). On Unix systems, see
|
|
|
|
* <code>chmod(2)</code> for details. Returns the number of files
|
|
|
|
* processed.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.chmod(0644, "testfile", "out") #=> 2
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_chmod(int argc, VALUE *argv, VALUE _)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-10-31 22:10:19 +03:00
|
|
|
mode_t mode;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2016-04-11 00:54:41 +03:00
|
|
|
apply2args(1);
|
2017-10-31 22:10:19 +03:00
|
|
|
mode = NUM2MODET(*argv++);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2016-04-11 00:59:01 +03:00
|
|
|
return apply2files(chmod_internal, argc, argv, &mode);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* file.chmod(mode_int) -> 0
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Changes permission bits on <i>file</i> to the bit pattern
|
|
|
|
* represented by <i>mode_int</i>. Actual effects are platform
|
|
|
|
* dependent; on Unix systems, see <code>chmod(2)</code> for details.
|
2019-03-22 14:04:59 +03:00
|
|
|
* Follows symbolic links. Also see File#lchmod.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* f = File.new("out", "w");
|
|
|
|
* f.chmod(0644) #=> 0
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_chmod(VALUE obj, VALUE vmode)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
2018-01-19 12:12:06 +03:00
|
|
|
mode_t mode;
|
2015-08-27 07:01:37 +03:00
|
|
|
#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
VALUE path;
|
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2018-01-19 12:12:06 +03:00
|
|
|
mode = NUM2MODET(vmode);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
GetOpenFile(obj, fptr);
|
2000-11-13 08:39:35 +03:00
|
|
|
#ifdef HAVE_FCHMOD
|
2015-08-27 07:01:37 +03:00
|
|
|
if (fchmod(fptr->fd, mode) == -1) {
|
|
|
|
if (HAVE_FCHMOD || errno != ENOSYS)
|
|
|
|
rb_sys_fail_path(fptr->pathv);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!HAVE_FCHMOD) return INT2FIX(0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
|
2008-08-23 04:47:54 +04:00
|
|
|
if (NIL_P(fptr->pathv)) return Qnil;
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
path = rb_str_encode_ospath(fptr->pathv);
|
|
|
|
if (chmod(RSTRING_PTR(path), mode) == -1)
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
|
2001-02-16 10:53:21 +03:00
|
|
|
#if defined(HAVE_LCHMOD)
|
2017-10-24 04:20:04 +03:00
|
|
|
static int
|
|
|
|
lchmod_internal(const char *path, void *mode)
|
2001-02-16 10:53:21 +03:00
|
|
|
{
|
2017-10-31 22:10:19 +03:00
|
|
|
return lchmod(path, *(mode_t *)mode);
|
2001-02-16 10:53:21 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.lchmod(mode_int, file_name, ...) -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* Equivalent to File::chmod, but does not follow symbolic links (so
|
|
|
|
* it will change the permissions associated with the link, not the
|
|
|
|
* file referenced by the link). Often not available.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2001-02-16 10:53:21 +03:00
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_lchmod(int argc, VALUE *argv, VALUE _)
|
2001-02-16 10:53:21 +03:00
|
|
|
{
|
2017-10-31 22:10:19 +03:00
|
|
|
mode_t mode;
|
2001-02-16 10:53:21 +03:00
|
|
|
|
2016-04-11 00:54:41 +03:00
|
|
|
apply2args(1);
|
2017-10-31 22:10:19 +03:00
|
|
|
mode = NUM2MODET(*argv++);
|
2001-02-16 10:53:21 +03:00
|
|
|
|
2017-10-31 22:10:19 +03:00
|
|
|
return apply2files(lchmod_internal, argc, argv, &mode);
|
2001-02-16 10:53:21 +03:00
|
|
|
}
|
|
|
|
#else
|
2009-04-16 18:17:14 +04:00
|
|
|
#define rb_file_s_lchmod rb_f_notimplement
|
2001-02-16 10:53:21 +03:00
|
|
|
#endif
|
|
|
|
|
2013-12-25 05:40:53 +04:00
|
|
|
static inline rb_uid_t
|
|
|
|
to_uid(VALUE u)
|
|
|
|
{
|
|
|
|
if (NIL_P(u)) {
|
|
|
|
return (rb_uid_t)-1;
|
|
|
|
}
|
|
|
|
return NUM2UIDT(u);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline rb_gid_t
|
|
|
|
to_gid(VALUE g)
|
|
|
|
{
|
|
|
|
if (NIL_P(g)) {
|
|
|
|
return (rb_gid_t)-1;
|
|
|
|
}
|
|
|
|
return NUM2GIDT(g);
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
struct chown_args {
|
2007-10-20 06:49:22 +04:00
|
|
|
rb_uid_t owner;
|
|
|
|
rb_gid_t group;
|
1998-01-16 15:13:05 +03:00
|
|
|
};
|
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
static int
|
|
|
|
chown_internal(const char *path, void *arg)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2005-09-12 19:02:46 +04:00
|
|
|
struct chown_args *args = arg;
|
2017-10-24 04:20:04 +03:00
|
|
|
return chown(path, args->owner, args->group);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2018-10-20 00:35:51 +03:00
|
|
|
* File.chown(owner_int, group_int, file_name, ...) -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Changes the owner and group of the named file(s) to the given
|
|
|
|
* numeric owner and group id's. Only a process with superuser
|
|
|
|
* privileges may change the owner of a file. The current owner of a
|
|
|
|
* file may change the file's group to any group to which the owner
|
|
|
|
* belongs. A <code>nil</code> or -1 owner or group id is ignored.
|
|
|
|
* Returns the number of files processed.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.chown(nil, 100, "testfile")
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_chown(int argc, VALUE *argv, VALUE _)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct chown_args arg;
|
|
|
|
|
2016-04-11 00:54:41 +03:00
|
|
|
apply2args(2);
|
|
|
|
arg.owner = to_uid(*argv++);
|
|
|
|
arg.group = to_gid(*argv++);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2016-04-11 00:59:01 +03:00
|
|
|
return apply2files(chown_internal, argc, argv, &arg);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* file.chown(owner_int, group_int ) -> 0
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Changes the owner and group of <i>file</i> to the given numeric
|
|
|
|
* owner and group id's. Only a process with superuser privileges may
|
|
|
|
* change the owner of a file. The current owner of a file may change
|
|
|
|
* the file's group to any group to which the owner belongs. A
|
|
|
|
* <code>nil</code> or -1 owner or group id is ignored. Follows
|
2019-03-22 14:04:59 +03:00
|
|
|
* symbolic links. See also File#lchown.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.new("testfile").chown(502, 1000)
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_chown(VALUE obj, VALUE owner, VALUE group)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
2013-12-25 04:47:26 +04:00
|
|
|
rb_uid_t o;
|
|
|
|
rb_gid_t g;
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
#ifndef HAVE_FCHOWN
|
|
|
|
VALUE path;
|
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2013-12-25 05:40:53 +04:00
|
|
|
o = to_uid(owner);
|
|
|
|
g = to_gid(group);
|
2004-11-22 20:02:45 +03:00
|
|
|
GetOpenFile(obj, fptr);
|
2009-02-18 09:35:38 +03:00
|
|
|
#ifndef HAVE_FCHOWN
|
2008-08-23 04:47:54 +04:00
|
|
|
if (NIL_P(fptr->pathv)) return Qnil;
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
path = rb_str_encode_ospath(fptr->pathv);
|
|
|
|
if (chown(RSTRING_PTR(path), o, g) == -1)
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
* rubyio.h, intern.h, io.c, file.c, process.c, ext/socket/socket.c,
ext/pty/pty.c, ext/io/wait/wait.c, ext/openssl/ossl_ssl.c:
Use own buffering mechanism instead of stdio.
* io.c, ext/stringio/stringio.c, test/ruby/ut_eof.rb:
EOF flag removed.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7473 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2004-12-06 11:40:30 +03:00
|
|
|
if (fchown(fptr->fd, o, g) == -1)
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
|
2009-06-22 16:23:06 +04:00
|
|
|
#if defined(HAVE_LCHOWN)
|
2017-10-24 04:20:04 +03:00
|
|
|
static int
|
|
|
|
lchown_internal(const char *path, void *arg)
|
2001-02-16 10:53:21 +03:00
|
|
|
{
|
2005-09-12 19:02:46 +04:00
|
|
|
struct chown_args *args = arg;
|
2017-10-24 04:20:04 +03:00
|
|
|
return lchown(path, args->owner, args->group);
|
2001-02-16 10:53:21 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2013-04-24 16:50:12 +04:00
|
|
|
* File.lchown(owner_int, group_int, file_name,..) -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* Equivalent to File::chown, but does not follow symbolic
|
2003-12-21 10:28:54 +03:00
|
|
|
* links (so it will change the owner associated with the link, not the
|
|
|
|
* file referenced by the link). Often not available. Returns number
|
|
|
|
* of files in the argument list.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2001-02-16 10:53:21 +03:00
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_lchown(int argc, VALUE *argv, VALUE _)
|
2001-02-16 10:53:21 +03:00
|
|
|
{
|
|
|
|
struct chown_args arg;
|
|
|
|
|
2016-04-11 00:54:41 +03:00
|
|
|
apply2args(2);
|
|
|
|
arg.owner = to_uid(*argv++);
|
|
|
|
arg.group = to_gid(*argv++);
|
2001-02-16 10:53:21 +03:00
|
|
|
|
2016-04-11 00:59:01 +03:00
|
|
|
return apply2files(lchown_internal, argc, argv, &arg);
|
2001-02-16 10:53:21 +03:00
|
|
|
}
|
|
|
|
#else
|
2009-04-16 20:58:06 +04:00
|
|
|
#define rb_file_s_lchown rb_f_notimplement
|
2001-02-16 10:53:21 +03:00
|
|
|
#endif
|
|
|
|
|
2009-04-06 14:26:20 +04:00
|
|
|
struct utime_args {
|
|
|
|
const struct timespec* tsp;
|
|
|
|
VALUE atime, mtime;
|
2017-11-29 12:59:20 +03:00
|
|
|
int follow; /* Whether to act on symlinks (1) or their referent (0) */
|
2009-04-06 14:26:20 +04:00
|
|
|
};
|
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
#ifdef UTIME_EINVAL
|
|
|
|
NORETURN(static void utime_failed(struct apply_arg *));
|
2009-04-06 14:26:20 +04:00
|
|
|
|
|
|
|
static void
|
2017-10-24 04:20:04 +03:00
|
|
|
utime_failed(struct apply_arg *aa)
|
2009-04-06 14:26:20 +04:00
|
|
|
{
|
2017-10-24 04:20:04 +03:00
|
|
|
int e = aa->errnum;
|
|
|
|
VALUE path = aa->fn[aa->i].path;
|
|
|
|
struct utime_args *ua = aa->arg;
|
|
|
|
|
|
|
|
if (ua->tsp && e == EINVAL) {
|
2009-04-06 14:26:20 +04:00
|
|
|
VALUE e[2], a = Qnil, m = Qnil;
|
|
|
|
int d = 0;
|
2017-10-24 04:20:04 +03:00
|
|
|
VALUE atime = ua->atime;
|
|
|
|
VALUE mtime = ua->mtime;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2009-04-06 14:26:20 +04:00
|
|
|
if (!NIL_P(atime)) {
|
|
|
|
a = rb_inspect(atime);
|
|
|
|
}
|
|
|
|
if (!NIL_P(mtime) && mtime != atime && !rb_equal(atime, mtime)) {
|
|
|
|
m = rb_inspect(mtime);
|
|
|
|
}
|
|
|
|
if (NIL_P(a)) e[0] = m;
|
|
|
|
else if (NIL_P(m) || rb_str_cmp(a, m) == 0) e[0] = a;
|
|
|
|
else {
|
|
|
|
e[0] = rb_str_plus(a, rb_str_new_cstr(" or "));
|
|
|
|
rb_str_append(e[0], m);
|
|
|
|
d = 1;
|
|
|
|
}
|
|
|
|
if (!NIL_P(e[0])) {
|
|
|
|
if (path) {
|
|
|
|
if (!d) e[0] = rb_str_dup(e[0]);
|
2012-02-24 11:48:34 +04:00
|
|
|
rb_str_append(rb_str_cat2(e[0], " for "), path);
|
2009-04-06 14:26:20 +04:00
|
|
|
}
|
|
|
|
e[1] = INT2FIX(EINVAL);
|
|
|
|
rb_exc_raise(rb_class_new_instance(2, e, rb_eSystemCallError));
|
|
|
|
}
|
|
|
|
}
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, path);
|
2009-04-06 14:26:20 +04:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* UTIME_EINVAL */
|
2009-04-06 14:26:20 +04:00
|
|
|
|
2007-11-19 12:48:00 +03:00
|
|
|
#if defined(HAVE_UTIMES)
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2022-10-03 16:59:22 +03:00
|
|
|
# if !defined(HAVE_UTIMENSAT)
|
|
|
|
/* utimensat() is not found, runtime check is not needed */
|
|
|
|
# elif defined(__APPLE__) && \
|
2022-06-27 07:17:36 +03:00
|
|
|
(!defined(MAC_OS_X_VERSION_13_0) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_13_0))
|
|
|
|
|
|
|
|
# if defined(__has_attribute) && __has_attribute(availability)
|
|
|
|
typedef int utimensat_func(int, const char *, const struct timespec [2], int);
|
|
|
|
|
2022-09-04 18:16:47 +03:00
|
|
|
RBIMPL_WARNING_PUSH()
|
|
|
|
RBIMPL_WARNING_IGNORED(-Wunguarded-availability-new)
|
2022-06-27 07:17:36 +03:00
|
|
|
static inline utimensat_func *
|
|
|
|
rb_utimensat(void)
|
|
|
|
{
|
|
|
|
return &utimensat;
|
|
|
|
}
|
2022-09-04 18:16:47 +03:00
|
|
|
RBIMPL_WARNING_POP()
|
2022-06-27 07:17:36 +03:00
|
|
|
|
|
|
|
# define utimensat rb_utimensat()
|
|
|
|
# else /* __API_AVAILABLE macro does nothing on gcc */
|
|
|
|
__attribute__((weak)) int utimensat(int, const char *, const struct timespec [2], int);
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif /* defined(__has_attribute) && __has_attribute(availability) */
|
|
|
|
# endif /* __APPLE__ && < MAC_OS_X_VERSION_13_0 */
|
2022-06-27 07:17:36 +03:00
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
static int
|
|
|
|
utime_internal(const char *path, void *arg)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-04-06 14:26:20 +04:00
|
|
|
struct utime_args *v = arg;
|
|
|
|
const struct timespec *tsp = v->tsp;
|
|
|
|
struct timeval tvbuf[2], *tvp = NULL;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2014-10-11 17:33:27 +04:00
|
|
|
#if defined(HAVE_UTIMENSAT)
|
2022-06-27 07:17:36 +03:00
|
|
|
# if defined(__APPLE__)
|
|
|
|
const int try_utimensat = utimensat != NULL;
|
|
|
|
const int try_utimensat_follow = utimensat != NULL;
|
2023-01-31 01:50:37 +03:00
|
|
|
# else /* !__APPLE__ */
|
2022-06-27 07:17:36 +03:00
|
|
|
# define TRY_UTIMENSAT 1
|
2007-11-19 12:48:00 +03:00
|
|
|
static int try_utimensat = 1;
|
2023-01-31 01:50:37 +03:00
|
|
|
# ifdef AT_SYMLINK_NOFOLLOW
|
2017-11-29 12:59:20 +03:00
|
|
|
static int try_utimensat_follow = 1;
|
2023-01-31 01:50:37 +03:00
|
|
|
# else
|
2017-11-29 12:59:20 +03:00
|
|
|
const int try_utimensat_follow = 0;
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif
|
|
|
|
# endif /* __APPLE__ */
|
2017-11-29 12:59:20 +03:00
|
|
|
int flags = 0;
|
|
|
|
|
|
|
|
if (v->follow ? try_utimensat_follow : try_utimensat) {
|
|
|
|
# ifdef AT_SYMLINK_NOFOLLOW
|
|
|
|
if (v->follow) {
|
|
|
|
flags = AT_SYMLINK_NOFOLLOW;
|
|
|
|
}
|
|
|
|
# endif
|
2007-11-19 12:48:00 +03:00
|
|
|
|
2022-06-27 07:17:36 +03:00
|
|
|
int result = utimensat(AT_FDCWD, path, tsp, flags);
|
|
|
|
# ifdef TRY_UTIMENSAT
|
|
|
|
if (result < 0 && errno == ENOSYS) {
|
2017-11-29 12:59:20 +03:00
|
|
|
# ifdef AT_SYMLINK_NOFOLLOW
|
2022-06-27 07:17:36 +03:00
|
|
|
try_utimensat_follow = 0;
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif /* AT_SYMLINK_NOFOLLOW */
|
2022-06-27 07:17:36 +03:00
|
|
|
if (!v->follow)
|
|
|
|
try_utimensat = 0;
|
2007-11-19 12:48:00 +03:00
|
|
|
}
|
2022-06-27 07:17:36 +03:00
|
|
|
else
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif /* TRY_UTIMESAT */
|
2022-06-27 07:17:36 +03:00
|
|
|
return result;
|
2007-11-19 12:48:00 +03:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* defined(HAVE_UTIMENSAT) */
|
2003-12-21 10:28:54 +03:00
|
|
|
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
if (tsp) {
|
|
|
|
tvbuf[0].tv_sec = tsp[0].tv_sec;
|
2009-04-06 11:38:52 +04:00
|
|
|
tvbuf[0].tv_usec = (int)(tsp[0].tv_nsec / 1000);
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
tvbuf[1].tv_sec = tsp[1].tv_sec;
|
2009-04-06 11:38:52 +04:00
|
|
|
tvbuf[1].tv_usec = (int)(tsp[1].tv_nsec / 1000);
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
tvp = tvbuf;
|
2007-03-03 16:37:02 +03:00
|
|
|
}
|
2017-11-29 12:59:20 +03:00
|
|
|
#ifdef HAVE_LUTIMES
|
|
|
|
if (v->follow) return lutimes(path, tvp);
|
|
|
|
#endif
|
2017-10-24 04:20:04 +03:00
|
|
|
return utimes(path, tvp);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2023-01-31 01:50:37 +03:00
|
|
|
#else /* !defined(HAVE_UTIMES) */
|
1998-01-16 15:13:05 +03:00
|
|
|
|
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-15 06:18:08 +03:00
|
|
|
#if !defined HAVE_UTIME_H && !defined HAVE_SYS_UTIME_H
|
1998-01-16 15:13:05 +03:00
|
|
|
struct utimbuf {
|
|
|
|
long actime;
|
|
|
|
long modtime;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
static int
|
|
|
|
utime_internal(const char *path, void *arg)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-04-06 14:26:20 +04:00
|
|
|
struct utime_args *v = arg;
|
|
|
|
const struct timespec *tsp = v->tsp;
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
struct utimbuf utbuf, *utp = NULL;
|
|
|
|
if (tsp) {
|
|
|
|
utbuf.actime = tsp[0].tv_sec;
|
|
|
|
utbuf.modtime = tsp[1].tv_sec;
|
|
|
|
utp = &utbuf;
|
|
|
|
}
|
2017-10-24 04:20:04 +03:00
|
|
|
return utime(path, utp);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* !defined(HAVE_UTIMES) */
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2017-11-29 12:59:20 +03:00
|
|
|
utime_internal_i(int argc, VALUE *argv, int follow)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-04-06 14:26:20 +04:00
|
|
|
struct utime_args args;
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
struct timespec tss[2], *tsp = NULL;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2016-04-11 00:54:41 +03:00
|
|
|
apply2args(2);
|
|
|
|
args.atime = *argv++;
|
|
|
|
args.mtime = *argv++;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2017-11-29 12:59:20 +03:00
|
|
|
args.follow = follow;
|
|
|
|
|
2009-04-06 14:26:20 +04:00
|
|
|
if (!NIL_P(args.atime) || !NIL_P(args.mtime)) {
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
tsp = tss;
|
2009-04-06 14:26:20 +04:00
|
|
|
tsp[0] = rb_time_timespec(args.atime);
|
2015-09-24 08:20:32 +03:00
|
|
|
if (args.atime == args.mtime)
|
|
|
|
tsp[1] = tsp[0];
|
|
|
|
else
|
|
|
|
tsp[1] = rb_time_timespec(args.mtime);
|
2007-03-04 17:38:02 +03:00
|
|
|
}
|
2009-04-06 14:26:20 +04:00
|
|
|
args.tsp = tsp;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2016-04-11 00:59:01 +03:00
|
|
|
return apply2files(utime_internal, argc, argv, &args);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:59:20 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2018-10-20 00:35:51 +03:00
|
|
|
* File.utime(atime, mtime, file_name, ...) -> integer
|
2017-11-29 12:59:20 +03:00
|
|
|
*
|
|
|
|
* Sets the access and modification times of each named file to the
|
|
|
|
* first two arguments. If a file is a symlink, this method acts upon
|
|
|
|
* its referent rather than the link itself; for the inverse
|
2017-12-04 15:31:44 +03:00
|
|
|
* behavior see File.lutime. Returns the number of file
|
2017-11-29 12:59:20 +03:00
|
|
|
* names in the argument list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_utime(int argc, VALUE *argv, VALUE _)
|
2017-11-29 12:59:20 +03:00
|
|
|
{
|
|
|
|
return utime_internal_i(argc, argv, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(HAVE_UTIMES) && (defined(HAVE_LUTIMES) || (defined(HAVE_UTIMENSAT) && defined(AT_SYMLINK_NOFOLLOW)))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2018-10-20 00:35:51 +03:00
|
|
|
* File.lutime(atime, mtime, file_name, ...) -> integer
|
2017-11-29 12:59:20 +03:00
|
|
|
*
|
|
|
|
* Sets the access and modification times of each named file to the
|
|
|
|
* first two arguments. If a file is a symlink, this method acts upon
|
|
|
|
* the link itself as opposed to its referent; for the inverse
|
2017-12-04 15:31:44 +03:00
|
|
|
* behavior, see File.utime. Returns the number of file
|
2017-11-29 12:59:20 +03:00
|
|
|
* names in the argument list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_lutime(int argc, VALUE *argv, VALUE _)
|
2017-11-29 12:59:20 +03:00
|
|
|
{
|
|
|
|
return utime_internal_i(argc, argv, TRUE);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define rb_file_s_lutime rb_f_notimplement
|
|
|
|
#endif
|
|
|
|
|
2015-08-27 04:03:55 +03:00
|
|
|
#ifdef RUBY_FUNCTION_NAME_STRING
|
2015-08-28 14:48:45 +03:00
|
|
|
# define syserr_fail2(e, s1, s2) syserr_fail2_in(RUBY_FUNCTION_NAME_STRING, e, s1, s2)
|
2015-08-27 04:03:55 +03:00
|
|
|
#else
|
2015-08-28 14:48:45 +03:00
|
|
|
# define syserr_fail2_in(func, e, s1, s2) syserr_fail2(e, s1, s2)
|
2015-08-27 04:03:55 +03:00
|
|
|
#endif
|
2015-08-28 14:48:45 +03:00
|
|
|
#define sys_fail2(s1, s2) syserr_fail2(errno, s1, s2)
|
|
|
|
NORETURN(static void syserr_fail2_in(const char *,int,VALUE,VALUE));
|
2003-07-20 21:17:52 +04:00
|
|
|
static void
|
2015-08-28 14:48:45 +03:00
|
|
|
syserr_fail2_in(const char *func, int e, VALUE s1, VALUE s2)
|
2003-07-20 21:17:52 +04:00
|
|
|
{
|
2012-02-24 11:48:34 +04:00
|
|
|
VALUE str;
|
2008-01-16 08:55:22 +03:00
|
|
|
#ifdef MAX_PATH
|
|
|
|
const int max_pathlen = MAX_PATH;
|
|
|
|
#else
|
|
|
|
const int max_pathlen = MAXPATHLEN;
|
|
|
|
#endif
|
|
|
|
|
2015-08-28 14:48:45 +03:00
|
|
|
if (e == EEXIST) {
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, rb_str_ellipsize(s2, max_pathlen));
|
2013-12-21 08:00:31 +04:00
|
|
|
}
|
2012-02-24 11:48:34 +04:00
|
|
|
str = rb_str_new_cstr("(");
|
|
|
|
rb_str_append(str, rb_str_ellipsize(s1, max_pathlen));
|
|
|
|
rb_str_cat2(str, ", ");
|
|
|
|
rb_str_append(str, rb_str_ellipsize(s2, max_pathlen));
|
|
|
|
rb_str_cat2(str, ")");
|
2015-08-27 04:03:55 +03:00
|
|
|
#ifdef RUBY_FUNCTION_NAME_STRING
|
2015-08-28 14:48:45 +03:00
|
|
|
rb_syserr_fail_path_in(func, e, str);
|
2015-08-27 04:03:55 +03:00
|
|
|
#else
|
2015-08-28 14:48:45 +03:00
|
|
|
rb_syserr_fail_path(e, str);
|
2015-08-27 04:03:55 +03:00
|
|
|
#endif
|
2003-07-20 21:17:52 +04:00
|
|
|
}
|
|
|
|
|
2009-04-16 20:58:06 +04:00
|
|
|
#ifdef HAVE_LINK
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.link(old_name, new_name) -> 0
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Creates a new name for an existing file using a hard link. Will not
|
|
|
|
* overwrite <i>new_name</i> if it already exists (raising a subclass
|
2019-03-22 14:04:59 +03:00
|
|
|
* of SystemCallError). Not available on all platforms.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.link("testfile", ".testfile") #=> 0
|
|
|
|
* IO.readlines(".testfile")[0] #=> "This is line one\n"
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_link(VALUE klass, VALUE from, VALUE to)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(from);
|
|
|
|
FilePathValue(to);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
from = rb_str_encode_ospath(from);
|
|
|
|
to = rb_str_encode_ospath(to);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2003-07-20 21:17:52 +04:00
|
|
|
if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
|
|
|
|
sys_fail2(from, to);
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
return INT2FIX(0);
|
2009-04-16 20:58:06 +04:00
|
|
|
}
|
2004-01-21 19:09:40 +03:00
|
|
|
#else
|
2009-04-16 20:58:06 +04:00
|
|
|
#define rb_file_s_link rb_f_notimplement
|
2004-01-21 19:09:40 +03:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2009-04-16 20:58:06 +04:00
|
|
|
#ifdef HAVE_SYMLINK
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.symlink(old_name, new_name) -> 0
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Creates a symbolic link called <i>new_name</i> for the existing file
|
2019-03-22 14:04:59 +03:00
|
|
|
* <i>old_name</i>. Raises a NotImplemented exception on
|
2003-12-21 10:28:54 +03:00
|
|
|
* platforms that do not support symbolic links.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.symlink("testfile", "link2test") #=> 0
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_symlink(VALUE klass, VALUE from, VALUE to)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(from);
|
|
|
|
FilePathValue(to);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
from = rb_str_encode_ospath(from);
|
|
|
|
to = rb_str_encode_ospath(to);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2003-07-20 21:17:52 +04:00
|
|
|
if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) {
|
|
|
|
sys_fail2(from, to);
|
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
return INT2FIX(0);
|
2009-04-16 20:58:06 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
2009-04-16 20:58:06 +04:00
|
|
|
#define rb_file_s_symlink rb_f_notimplement
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
2009-04-16 20:58:06 +04:00
|
|
|
#ifdef HAVE_READLINK
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.readlink(link_name) -> file_name
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the name of the file referenced by the given link.
|
|
|
|
* Not available on all platforms.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.symlink("testfile", "link2test") #=> 0
|
|
|
|
* File.readlink("link2test") #=> "testfile"
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_readlink(VALUE klass, VALUE path)
|
2012-01-25 06:32:06 +04:00
|
|
|
{
|
2015-09-02 10:58:24 +03:00
|
|
|
return rb_readlink(path, rb_filesystem_encoding());
|
2012-01-25 06:32:06 +04:00
|
|
|
}
|
|
|
|
|
2017-11-19 08:03:17 +03:00
|
|
|
struct readlink_arg {
|
|
|
|
const char *path;
|
|
|
|
char *buf;
|
|
|
|
size_t size;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *
|
|
|
|
nogvl_readlink(void *ptr)
|
|
|
|
{
|
|
|
|
struct readlink_arg *ra = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)readlink(ra->path, ra->buf, ra->size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t
|
|
|
|
readlink_without_gvl(VALUE path, VALUE buf, size_t size)
|
|
|
|
{
|
|
|
|
struct readlink_arg ra;
|
|
|
|
|
|
|
|
ra.path = RSTRING_PTR(path);
|
|
|
|
ra.buf = RSTRING_PTR(buf);
|
|
|
|
ra.size = size;
|
|
|
|
|
|
|
|
return (ssize_t)rb_thread_call_without_gvl(nogvl_readlink, &ra,
|
|
|
|
RUBY_UBF_IO, 0);
|
|
|
|
}
|
|
|
|
|
2015-01-24 15:24:27 +03:00
|
|
|
VALUE
|
2015-09-02 10:58:24 +03:00
|
|
|
rb_readlink(VALUE path, rb_encoding *enc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-11-08 09:43:14 +03:00
|
|
|
int size = 100;
|
2009-04-06 11:38:52 +04:00
|
|
|
ssize_t rv;
|
2001-11-08 09:43:14 +03:00
|
|
|
VALUE v;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(path);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
path = rb_str_encode_ospath(path);
|
2015-09-02 10:58:24 +03:00
|
|
|
v = rb_enc_str_new(0, size, enc);
|
2017-11-19 08:03:17 +03:00
|
|
|
while ((rv = readlink_without_gvl(path, v, size)) == size
|
2005-11-14 17:52:55 +03:00
|
|
|
#ifdef _AIX
|
|
|
|
|| (rv < 0 && errno == ERANGE) /* quirky behavior of GPFS */
|
2005-11-06 14:18:57 +03:00
|
|
|
#endif
|
2005-11-14 17:52:55 +03:00
|
|
|
) {
|
2012-09-16 13:24:44 +04:00
|
|
|
rb_str_modify_expand(v, size);
|
2001-11-08 09:43:14 +03:00
|
|
|
size *= 2;
|
2013-11-26 11:30:37 +04:00
|
|
|
rb_str_set_len(v, size);
|
2001-11-08 09:43:14 +03:00
|
|
|
}
|
2002-09-02 12:02:56 +04:00
|
|
|
if (rv < 0) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
2012-09-16 13:24:44 +04:00
|
|
|
rb_str_resize(v, 0);
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, path);
|
2002-09-02 12:02:56 +04:00
|
|
|
}
|
2012-09-16 13:24:44 +04:00
|
|
|
rb_str_resize(v, rv);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-11-08 09:43:14 +03:00
|
|
|
return v;
|
2009-04-16 20:58:06 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
2009-04-16 20:58:06 +04:00
|
|
|
#define rb_file_s_readlink rb_f_notimplement
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
2017-10-24 04:20:04 +03:00
|
|
|
static int
|
|
|
|
unlink_internal(const char *path, void *arg)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-10-24 04:20:04 +03:00
|
|
|
return unlink(path);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.delete(file_name, ...) -> integer
|
|
|
|
* File.unlink(file_name, ...) -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Deletes the named files, returning the number of names
|
|
|
|
* passed as arguments. Raises an exception on any error.
|
2017-10-21 16:49:39 +03:00
|
|
|
* Since the underlying implementation relies on the
|
|
|
|
* <code>unlink(2)</code> system call, the type of
|
|
|
|
* exception raised depends on its error type (see
|
|
|
|
* https://linux.die.net/man/2/unlink) and has the form of
|
2019-03-22 14:04:59 +03:00
|
|
|
* e.g. Errno::ENOENT.
|
2017-10-21 16:49:39 +03:00
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* See also Dir::rmdir.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2016-04-11 00:54:41 +03:00
|
|
|
rb_file_s_unlink(int argc, VALUE *argv, VALUE klass)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2016-04-11 00:59:01 +03:00
|
|
|
return apply2files(unlink_internal, argc, argv, 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2017-10-02 00:19:24 +03:00
|
|
|
struct rename_args {
|
|
|
|
const char *src;
|
|
|
|
const char *dst;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *
|
|
|
|
no_gvl_rename(void *ptr)
|
|
|
|
{
|
|
|
|
struct rename_args *ra = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)rename(ra->src, ra->dst);
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.rename(old_name, new_name) -> 0
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* Renames the given file to the new name. Raises a SystemCallError
|
|
|
|
* if the file cannot be renamed.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.rename("afile", "afile.bak") #=> 0
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-10-02 00:19:24 +03:00
|
|
|
struct rename_args ra;
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
VALUE f, t;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(from);
|
|
|
|
FilePathValue(to);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
f = rb_str_encode_ospath(from);
|
|
|
|
t = rb_str_encode_ospath(to);
|
2017-10-02 00:19:24 +03:00
|
|
|
ra.src = StringValueCStr(f);
|
|
|
|
ra.dst = StringValueCStr(t);
|
2006-08-19 06:29:18 +04:00
|
|
|
#if defined __CYGWIN__
|
|
|
|
errno = 0;
|
|
|
|
#endif
|
2017-10-02 00:19:24 +03:00
|
|
|
if ((int)(VALUE)rb_thread_call_without_gvl(no_gvl_rename, &ra,
|
|
|
|
RUBY_UBF_IO, 0) < 0) {
|
2015-08-28 14:48:45 +03:00
|
|
|
int e = errno;
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
#if defined DOSISH
|
2015-08-28 14:48:45 +03:00
|
|
|
switch (e) {
|
2007-07-22 09:33:54 +04:00
|
|
|
case EEXIST:
|
2017-10-02 04:57:27 +03:00
|
|
|
if (chmod(ra.dst, 0666) == 0 &&
|
|
|
|
unlink(ra.dst) == 0 &&
|
|
|
|
rename(ra.src, ra.dst) == 0)
|
2003-07-30 04:32:03 +04:00
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
2001-02-24 20:51:02 +03:00
|
|
|
#endif
|
2015-08-28 14:48:45 +03:00
|
|
|
syserr_fail2(e, from, to);
|
2001-02-24 20:51:02 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.umask() -> integer
|
|
|
|
* File.umask(integer) -> integer
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns the current umask value for this process. If the optional
|
|
|
|
* argument is given, set the umask to that value and return the
|
|
|
|
* previous value. Umask values are <em>subtracted</em> from the
|
|
|
|
* default permissions, so a umask of <code>0222</code> would make a
|
|
|
|
* file read-only for everyone.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.umask(0006) #=> 18
|
|
|
|
* File.umask #=> 6
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_umask(int argc, VALUE *argv, VALUE _)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-10-31 22:10:19 +03:00
|
|
|
mode_t omask = 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2019-07-14 11:15:44 +03:00
|
|
|
switch (argc) {
|
|
|
|
case 0:
|
1999-01-20 07:59:39 +03:00
|
|
|
omask = umask(0);
|
1998-01-16 15:13:05 +03:00
|
|
|
umask(omask);
|
2019-07-14 11:15:44 +03:00
|
|
|
break;
|
|
|
|
case 1:
|
2017-10-31 22:10:19 +03:00
|
|
|
omask = umask(NUM2MODET(argv[0]));
|
2019-07-14 11:15:44 +03:00
|
|
|
break;
|
|
|
|
default:
|
2019-07-14 11:16:35 +03:00
|
|
|
rb_error_arity(argc, 0, 1);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2017-10-31 22:10:19 +03:00
|
|
|
return MODET2NUM(omask);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2008-03-08 12:51:00 +03:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
#undef DOSISH
|
|
|
|
#endif
|
|
|
|
#if defined __CYGWIN__ || defined DOSISH
|
2003-02-12 17:56:45 +03:00
|
|
|
#define DOSISH_UNC
|
2008-03-08 12:51:00 +03:00
|
|
|
#define DOSISH_DRIVE_LETTER
|
2010-03-15 01:16:12 +03:00
|
|
|
#define FILE_ALT_SEPARATOR '\\'
|
|
|
|
#endif
|
|
|
|
#ifdef FILE_ALT_SEPARATOR
|
|
|
|
#define isdirsep(x) ((x) == '/' || (x) == FILE_ALT_SEPARATOR)
|
2017-10-11 07:45:08 +03:00
|
|
|
# ifdef DOSISH
|
2010-03-15 01:33:09 +03:00
|
|
|
static const char file_alt_separator[] = {FILE_ALT_SEPARATOR, '\0'};
|
2017-10-11 07:45:08 +03:00
|
|
|
# endif
|
1999-08-13 09:45:20 +04:00
|
|
|
#else
|
|
|
|
#define isdirsep(x) ((x) == '/')
|
|
|
|
#endif
|
2008-03-08 12:51:00 +03:00
|
|
|
|
2009-02-18 06:04:49 +03:00
|
|
|
#ifndef USE_NTFS
|
2023-01-31 01:50:37 +03:00
|
|
|
# if defined _WIN32
|
|
|
|
# define USE_NTFS 1
|
|
|
|
# else
|
|
|
|
# define USE_NTFS 0
|
|
|
|
# endif
|
2009-02-18 06:04:49 +03:00
|
|
|
#endif
|
2023-01-31 01:50:37 +03:00
|
|
|
|
2016-12-06 10:21:55 +03:00
|
|
|
#ifndef USE_NTFS_ADS
|
|
|
|
# if USE_NTFS
|
|
|
|
# define USE_NTFS_ADS 1
|
|
|
|
# else
|
|
|
|
# define USE_NTFS_ADS 0
|
|
|
|
# endif
|
|
|
|
#endif
|
2008-05-15 10:34:02 +04:00
|
|
|
|
|
|
|
#if USE_NTFS
|
2009-05-31 18:26:40 +04:00
|
|
|
#define istrailinggarbage(x) ((x) == '.' || (x) == ' ')
|
2008-05-15 10:34:02 +04:00
|
|
|
#else
|
2009-05-31 18:26:40 +04:00
|
|
|
#define istrailinggarbage(x) 0
|
2008-05-15 10:34:02 +04:00
|
|
|
#endif
|
2023-01-31 01:50:37 +03:00
|
|
|
|
2016-12-06 10:21:55 +03:00
|
|
|
#if USE_NTFS_ADS
|
|
|
|
# define isADS(x) ((x) == ':')
|
|
|
|
#else
|
|
|
|
# define isADS(x) 0
|
|
|
|
#endif
|
2008-05-15 10:34:02 +04:00
|
|
|
|
2012-01-25 06:32:06 +04:00
|
|
|
#define Next(p, e, enc) ((p) + rb_enc_mbclen((p), (e), (enc)))
|
|
|
|
#define Inc(p, e, enc) ((p) = Next((p), (e), (enc)))
|
2001-07-24 19:11:02 +04:00
|
|
|
|
2010-03-16 05:23:51 +03:00
|
|
|
#if defined(DOSISH_UNC)
|
|
|
|
#define has_unc(buf) (isdirsep((buf)[0]) && isdirsep((buf)[1]))
|
|
|
|
#else
|
|
|
|
#define has_unc(buf) 0
|
|
|
|
#endif
|
|
|
|
|
2003-02-12 17:56:45 +03:00
|
|
|
#ifdef DOSISH_DRIVE_LETTER
|
2003-01-06 12:44:15 +03:00
|
|
|
static inline int
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
has_drive_letter(const char *buf)
|
2003-01-06 12:44:15 +03:00
|
|
|
{
|
|
|
|
if (ISALPHA(buf[0]) && buf[1] == ':') {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-05 09:29:37 +04:00
|
|
|
#ifndef _WIN32
|
* gc.c (Init_stack): stack region is far smaller than usual if
pthread is used.
* marshal.c (w_extended): singleton methods should not be checked
when dumping via marshal_dump() or _dump(). [ruby-talk:85909]
* file.c (getcwdofdrv): avoid using getcwd() directly, use
my_getcwd() instead.
* merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine
<sunshine@sunshineco.com>. [ruby-core:01596]
* marshal.c (w_object): LINK check earlier than anything else,
i.e. do not dump TYPE_IVAR for already dumped objects.
(ruby-bugs PR#1220)
* eval.c (rb_eval): call "inherited" only when a new class is
generated; not on reopening.
* eval.c (eval): prepend error position in evaluating string to
* configure.in: revived NextStep, OpenStep, and Rhapsody ports which
had become unbuildable; enhanced --enable-fat-binary option so that
it accepts a list of desired architectures (rather than assuming a
fixed list), or defaults to a platform-appropriate list if user does
not provide an explicit list; made the default list of architectures
for MAB (fat binary) more comprehensive; now uses -fno-common even
when building the interpreter (in addition to using it for
extensions), thus allowing the interpreter to be embedded into a
plugin module of an external project (in addition to allowing
embedding directly into an application); added checks for
<netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
ensures that -I/usr/local/include is employed when extensions'
extconf.rb scripts invoke have_header() since extension checks on
NextStep and OpenStep will fail without it if the desired resource
resides in the /usr/local tree; fixed formatting of --help message.
* Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
(see configure's --enable-fat-binary option); added rule for new
missing/getcwd.c.
* defines.h: fixed endian handling during MAB build (see configure's
--enable-fat-binary option) to ensure that all portions of the
project see the correct WORDS_BIGENDIAN value (some extension modules
were getting the wrong endian setting); added missing constants
GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
define in NeXT section.
* dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
NextStep since, on some installations, this value always resolves
uselessly to zero.
* dln.c: added error reporting to NextStep extension loader since the
previous behavior of failing silently was not useful; now ensures
that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
on Rhapsody since this header lacks multiple-include protection,
which resulted in "redefinition" compilation errors.
* main.c: also create hard reference to objc_msgSend() on NeXT
platforms (in addition to Apple platforms).
* lib/mkmf.rb: now exports XCFLAGS from configure script to extension
makefiles so that extensions can be built MAB (see configure's
--enable-fat-binary option); also utilize XCFLAGS in cc_command()
(but not cpp_command() because MAB flags are incompatible with
direct invocation of `cpp').
* ext/curses/extconf.rb: now additionally checks for presence of these
curses functions which are not present on NextStep or Openstep:
bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
wscrl(), wsetscrreg()
* ext/curses/curses.c: added appropriate #ifdef's for additional set of
curses functions now checked by extconf.rb; fixed curses_bkgd() and
window_bkgd() to correctly return boolean result rather than numeric
result; fixed window_getbkgd() to correctly signal an error by
returning nil rather than -1.
* ext/etc/etc.c: setup_passwd() and setup_group() now check for null
pointers before invoking rb_tainted_str_new2() upon fields extracted
from `struct passwd' and `struct group' since null pointers in some
fields are common on NextStep/OpenStep (especially so for the
`pw_comment' field) and rb_tainted_str_new2() throws an exception
when it receives a null pointer.
* ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
* ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
gethostbyaddr(), and gethostbyname() from (const char*) to non-const
(char*) for older platforms such as NextStep and OpenStep.
* ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup(); include
<netinet/in_systm.h> if present for NextStep and OpenStep; cast first
argument of gethostbyaddr() and getservbyname() from (const char*) to
non-const (char*) for older platforms.
* ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-22 07:00:03 +03:00
|
|
|
static char*
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
getcwdofdrv(int drv)
|
2003-01-06 12:44:15 +03:00
|
|
|
{
|
|
|
|
char drive[4];
|
* gc.c (Init_stack): stack region is far smaller than usual if
pthread is used.
* marshal.c (w_extended): singleton methods should not be checked
when dumping via marshal_dump() or _dump(). [ruby-talk:85909]
* file.c (getcwdofdrv): avoid using getcwd() directly, use
my_getcwd() instead.
* merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine
<sunshine@sunshineco.com>. [ruby-core:01596]
* marshal.c (w_object): LINK check earlier than anything else,
i.e. do not dump TYPE_IVAR for already dumped objects.
(ruby-bugs PR#1220)
* eval.c (rb_eval): call "inherited" only when a new class is
generated; not on reopening.
* eval.c (eval): prepend error position in evaluating string to
* configure.in: revived NextStep, OpenStep, and Rhapsody ports which
had become unbuildable; enhanced --enable-fat-binary option so that
it accepts a list of desired architectures (rather than assuming a
fixed list), or defaults to a platform-appropriate list if user does
not provide an explicit list; made the default list of architectures
for MAB (fat binary) more comprehensive; now uses -fno-common even
when building the interpreter (in addition to using it for
extensions), thus allowing the interpreter to be embedded into a
plugin module of an external project (in addition to allowing
embedding directly into an application); added checks for
<netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
ensures that -I/usr/local/include is employed when extensions'
extconf.rb scripts invoke have_header() since extension checks on
NextStep and OpenStep will fail without it if the desired resource
resides in the /usr/local tree; fixed formatting of --help message.
* Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
(see configure's --enable-fat-binary option); added rule for new
missing/getcwd.c.
* defines.h: fixed endian handling during MAB build (see configure's
--enable-fat-binary option) to ensure that all portions of the
project see the correct WORDS_BIGENDIAN value (some extension modules
were getting the wrong endian setting); added missing constants
GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
define in NeXT section.
* dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
NextStep since, on some installations, this value always resolves
uselessly to zero.
* dln.c: added error reporting to NextStep extension loader since the
previous behavior of failing silently was not useful; now ensures
that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
on Rhapsody since this header lacks multiple-include protection,
which resulted in "redefinition" compilation errors.
* main.c: also create hard reference to objc_msgSend() on NeXT
platforms (in addition to Apple platforms).
* lib/mkmf.rb: now exports XCFLAGS from configure script to extension
makefiles so that extensions can be built MAB (see configure's
--enable-fat-binary option); also utilize XCFLAGS in cc_command()
(but not cpp_command() because MAB flags are incompatible with
direct invocation of `cpp').
* ext/curses/extconf.rb: now additionally checks for presence of these
curses functions which are not present on NextStep or Openstep:
bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
wscrl(), wsetscrreg()
* ext/curses/curses.c: added appropriate #ifdef's for additional set of
curses functions now checked by extconf.rb; fixed curses_bkgd() and
window_bkgd() to correctly return boolean result rather than numeric
result; fixed window_getbkgd() to correctly signal an error by
returning nil rather than -1.
* ext/etc/etc.c: setup_passwd() and setup_group() now check for null
pointers before invoking rb_tainted_str_new2() upon fields extracted
from `struct passwd' and `struct group' since null pointers in some
fields are common on NextStep/OpenStep (especially so for the
`pw_comment' field) and rb_tainted_str_new2() throws an exception
when it receives a null pointer.
* ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
* ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
gethostbyaddr(), and gethostbyname() from (const char*) to non-const
(char*) for older platforms such as NextStep and OpenStep.
* ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup(); include
<netinet/in_systm.h> if present for NextStep and OpenStep; cast first
argument of gethostbyaddr() and getservbyname() from (const char*) to
non-const (char*) for older platforms.
* ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-22 07:00:03 +03:00
|
|
|
char *drvcwd, *oldcwd;
|
2003-01-06 12:44:15 +03:00
|
|
|
|
|
|
|
drive[0] = drv;
|
|
|
|
drive[1] = ':';
|
|
|
|
drive[2] = '\0';
|
|
|
|
|
|
|
|
/* the only way that I know to get the current directory
|
|
|
|
of a particular drive is to change chdir() to that drive,
|
|
|
|
so save the old cwd before chdir()
|
|
|
|
*/
|
2017-11-26 04:36:33 +03:00
|
|
|
oldcwd = ruby_getcwd();
|
2003-01-06 12:44:15 +03:00
|
|
|
if (chdir(drive) == 0) {
|
2017-11-26 04:36:33 +03:00
|
|
|
drvcwd = ruby_getcwd();
|
2003-01-06 12:44:15 +03:00
|
|
|
chdir(oldcwd);
|
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 14:01:40 +04:00
|
|
|
xfree(oldcwd);
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* perhaps the drive is not exist. we return only drive letter */
|
* gc.c (Init_stack): stack region is far smaller than usual if
pthread is used.
* marshal.c (w_extended): singleton methods should not be checked
when dumping via marshal_dump() or _dump(). [ruby-talk:85909]
* file.c (getcwdofdrv): avoid using getcwd() directly, use
my_getcwd() instead.
* merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine
<sunshine@sunshineco.com>. [ruby-core:01596]
* marshal.c (w_object): LINK check earlier than anything else,
i.e. do not dump TYPE_IVAR for already dumped objects.
(ruby-bugs PR#1220)
* eval.c (rb_eval): call "inherited" only when a new class is
generated; not on reopening.
* eval.c (eval): prepend error position in evaluating string to
* configure.in: revived NextStep, OpenStep, and Rhapsody ports which
had become unbuildable; enhanced --enable-fat-binary option so that
it accepts a list of desired architectures (rather than assuming a
fixed list), or defaults to a platform-appropriate list if user does
not provide an explicit list; made the default list of architectures
for MAB (fat binary) more comprehensive; now uses -fno-common even
when building the interpreter (in addition to using it for
extensions), thus allowing the interpreter to be embedded into a
plugin module of an external project (in addition to allowing
embedding directly into an application); added checks for
<netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
ensures that -I/usr/local/include is employed when extensions'
extconf.rb scripts invoke have_header() since extension checks on
NextStep and OpenStep will fail without it if the desired resource
resides in the /usr/local tree; fixed formatting of --help message.
* Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
(see configure's --enable-fat-binary option); added rule for new
missing/getcwd.c.
* defines.h: fixed endian handling during MAB build (see configure's
--enable-fat-binary option) to ensure that all portions of the
project see the correct WORDS_BIGENDIAN value (some extension modules
were getting the wrong endian setting); added missing constants
GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
define in NeXT section.
* dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
NextStep since, on some installations, this value always resolves
uselessly to zero.
* dln.c: added error reporting to NextStep extension loader since the
previous behavior of failing silently was not useful; now ensures
that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
on Rhapsody since this header lacks multiple-include protection,
which resulted in "redefinition" compilation errors.
* main.c: also create hard reference to objc_msgSend() on NeXT
platforms (in addition to Apple platforms).
* lib/mkmf.rb: now exports XCFLAGS from configure script to extension
makefiles so that extensions can be built MAB (see configure's
--enable-fat-binary option); also utilize XCFLAGS in cc_command()
(but not cpp_command() because MAB flags are incompatible with
direct invocation of `cpp').
* ext/curses/extconf.rb: now additionally checks for presence of these
curses functions which are not present on NextStep or Openstep:
bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
wscrl(), wsetscrreg()
* ext/curses/curses.c: added appropriate #ifdef's for additional set of
curses functions now checked by extconf.rb; fixed curses_bkgd() and
window_bkgd() to correctly return boolean result rather than numeric
result; fixed window_getbkgd() to correctly signal an error by
returning nil rather than -1.
* ext/etc/etc.c: setup_passwd() and setup_group() now check for null
pointers before invoking rb_tainted_str_new2() upon fields extracted
from `struct passwd' and `struct group' since null pointers in some
fields are common on NextStep/OpenStep (especially so for the
`pw_comment' field) and rb_tainted_str_new2() throws an exception
when it receives a null pointer.
* ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
* ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
gethostbyaddr(), and gethostbyname() from (const char*) to non-const
(char*) for older platforms such as NextStep and OpenStep.
* ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup(); include
<netinet/in_systm.h> if present for NextStep and OpenStep; cast first
argument of gethostbyaddr() and getservbyname() from (const char*) to
non-const (char*) for older platforms.
* ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-22 07:00:03 +03:00
|
|
|
drvcwd = strdup(drive);
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
* gc.c (Init_stack): stack region is far smaller than usual if
pthread is used.
* marshal.c (w_extended): singleton methods should not be checked
when dumping via marshal_dump() or _dump(). [ruby-talk:85909]
* file.c (getcwdofdrv): avoid using getcwd() directly, use
my_getcwd() instead.
* merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine
<sunshine@sunshineco.com>. [ruby-core:01596]
* marshal.c (w_object): LINK check earlier than anything else,
i.e. do not dump TYPE_IVAR for already dumped objects.
(ruby-bugs PR#1220)
* eval.c (rb_eval): call "inherited" only when a new class is
generated; not on reopening.
* eval.c (eval): prepend error position in evaluating string to
* configure.in: revived NextStep, OpenStep, and Rhapsody ports which
had become unbuildable; enhanced --enable-fat-binary option so that
it accepts a list of desired architectures (rather than assuming a
fixed list), or defaults to a platform-appropriate list if user does
not provide an explicit list; made the default list of architectures
for MAB (fat binary) more comprehensive; now uses -fno-common even
when building the interpreter (in addition to using it for
extensions), thus allowing the interpreter to be embedded into a
plugin module of an external project (in addition to allowing
embedding directly into an application); added checks for
<netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
ensures that -I/usr/local/include is employed when extensions'
extconf.rb scripts invoke have_header() since extension checks on
NextStep and OpenStep will fail without it if the desired resource
resides in the /usr/local tree; fixed formatting of --help message.
* Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
(see configure's --enable-fat-binary option); added rule for new
missing/getcwd.c.
* defines.h: fixed endian handling during MAB build (see configure's
--enable-fat-binary option) to ensure that all portions of the
project see the correct WORDS_BIGENDIAN value (some extension modules
were getting the wrong endian setting); added missing constants
GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
define in NeXT section.
* dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
NextStep since, on some installations, this value always resolves
uselessly to zero.
* dln.c: added error reporting to NextStep extension loader since the
previous behavior of failing silently was not useful; now ensures
that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
on Rhapsody since this header lacks multiple-include protection,
which resulted in "redefinition" compilation errors.
* main.c: also create hard reference to objc_msgSend() on NeXT
platforms (in addition to Apple platforms).
* lib/mkmf.rb: now exports XCFLAGS from configure script to extension
makefiles so that extensions can be built MAB (see configure's
--enable-fat-binary option); also utilize XCFLAGS in cc_command()
(but not cpp_command() because MAB flags are incompatible with
direct invocation of `cpp').
* ext/curses/extconf.rb: now additionally checks for presence of these
curses functions which are not present on NextStep or Openstep:
bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
wscrl(), wsetscrreg()
* ext/curses/curses.c: added appropriate #ifdef's for additional set of
curses functions now checked by extconf.rb; fixed curses_bkgd() and
window_bkgd() to correctly return boolean result rather than numeric
result; fixed window_getbkgd() to correctly signal an error by
returning nil rather than -1.
* ext/etc/etc.c: setup_passwd() and setup_group() now check for null
pointers before invoking rb_tainted_str_new2() upon fields extracted
from `struct passwd' and `struct group' since null pointers in some
fields are common on NextStep/OpenStep (especially so for the
`pw_comment' field) and rb_tainted_str_new2() throws an exception
when it receives a null pointer.
* ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
* ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
gethostbyaddr(), and gethostbyname() from (const char*) to non-const
(char*) for older platforms such as NextStep and OpenStep.
* ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup(); include
<netinet/in_systm.h> if present for NextStep and OpenStep; cast first
argument of gethostbyaddr() and getservbyname() from (const char*) to
non-const (char*) for older platforms.
* ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-22 07:00:03 +03:00
|
|
|
return drvcwd;
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
2010-03-16 05:23:51 +03:00
|
|
|
|
|
|
|
static inline int
|
|
|
|
not_same_drive(VALUE path, int drive)
|
|
|
|
{
|
|
|
|
const char *p = RSTRING_PTR(path);
|
|
|
|
if (RSTRING_LEN(path) < 2) return 0;
|
|
|
|
if (has_drive_letter(p)) {
|
|
|
|
return TOLOWER(p[0]) != TOLOWER(drive);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return has_unc(p);
|
|
|
|
}
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* _WIN32 */
|
|
|
|
#endif /* DOSISH_DRIVE_LETTER */
|
2003-01-06 12:44:15 +03:00
|
|
|
|
2003-02-12 17:56:45 +03:00
|
|
|
static inline char *
|
2012-01-25 06:32:06 +04:00
|
|
|
skiproot(const char *path, const char *end, rb_encoding *enc)
|
2003-02-12 17:56:45 +03:00
|
|
|
{
|
|
|
|
#ifdef DOSISH_DRIVE_LETTER
|
2012-01-25 06:32:06 +04:00
|
|
|
if (path + 2 <= end && has_drive_letter(path)) path += 2;
|
2003-02-12 17:56:45 +03:00
|
|
|
#endif
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end && isdirsep(*path)) path++;
|
2003-02-12 17:56:45 +03:00
|
|
|
return (char *)path;
|
|
|
|
}
|
|
|
|
|
2012-01-25 06:32:06 +04:00
|
|
|
#define nextdirsep rb_enc_path_next
|
2003-12-15 07:07:03 +03:00
|
|
|
char *
|
2014-06-03 00:23:47 +04:00
|
|
|
rb_enc_path_next(const char *s, const char *e, rb_encoding *enc)
|
2003-02-16 13:22:36 +03:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
while (s < e && !isdirsep(*s)) {
|
|
|
|
Inc(s, e, enc);
|
2003-02-16 13:22:36 +03:00
|
|
|
}
|
|
|
|
return (char *)s;
|
|
|
|
}
|
|
|
|
|
2009-02-18 06:04:49 +03:00
|
|
|
#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
|
2012-01-25 06:32:06 +04:00
|
|
|
#define skipprefix rb_enc_path_skip_prefix
|
2005-11-21 16:21:47 +03:00
|
|
|
#else
|
2012-01-25 06:32:06 +04:00
|
|
|
#define skipprefix(path, end, enc) (path)
|
2005-11-21 16:21:47 +03:00
|
|
|
#endif
|
2003-12-15 07:07:03 +03:00
|
|
|
char *
|
2014-06-03 00:23:47 +04:00
|
|
|
rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc)
|
2003-02-20 12:11:05 +03:00
|
|
|
{
|
2009-02-18 06:04:49 +03:00
|
|
|
#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
|
2003-02-20 12:11:05 +03:00
|
|
|
#ifdef DOSISH_UNC
|
2012-01-25 06:32:06 +04:00
|
|
|
if (path + 2 <= end && isdirsep(path[0]) && isdirsep(path[1])) {
|
2005-11-22 08:39:50 +03:00
|
|
|
path += 2;
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end && isdirsep(*path)) path++;
|
|
|
|
if ((path = rb_enc_path_next(path, end, enc)) < end && path[0] && path[1] && !isdirsep(path[1]))
|
|
|
|
path = rb_enc_path_next(path + 1, end, enc);
|
2003-02-20 12:11:05 +03:00
|
|
|
return (char *)path;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DOSISH_DRIVE_LETTER
|
|
|
|
if (has_drive_letter(path))
|
|
|
|
return (char *)(path + 2);
|
2003-12-15 07:07:03 +03:00
|
|
|
#endif
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER) */
|
2003-02-20 12:11:05 +03:00
|
|
|
return (char *)path;
|
|
|
|
}
|
|
|
|
|
2010-06-29 09:20:06 +04:00
|
|
|
static inline char *
|
2012-01-25 06:32:06 +04:00
|
|
|
skipprefixroot(const char *path, const char *end, rb_encoding *enc)
|
2010-06-29 09:20:06 +04:00
|
|
|
{
|
|
|
|
#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
|
2012-01-25 06:32:06 +04:00
|
|
|
char *p = skipprefix(path, end, enc);
|
2010-06-29 09:20:06 +04:00
|
|
|
while (isdirsep(*p)) p++;
|
|
|
|
return p;
|
|
|
|
#else
|
2012-01-25 06:32:06 +04:00
|
|
|
return skiproot(path, end, enc);
|
2010-06-29 09:20:06 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-01-25 06:32:06 +04:00
|
|
|
#define strrdirsep rb_enc_path_last_separator
|
2003-12-15 07:07:03 +03:00
|
|
|
char *
|
2014-06-03 00:23:47 +04:00
|
|
|
rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc)
|
2001-07-24 19:11:02 +04:00
|
|
|
{
|
|
|
|
char *last = NULL;
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end) {
|
2001-07-24 19:11:02 +04:00
|
|
|
if (isdirsep(*path)) {
|
2003-02-12 17:56:45 +03:00
|
|
|
const char *tmp = path++;
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end && isdirsep(*path)) path++;
|
|
|
|
if (path >= end) break;
|
2003-02-12 17:56:45 +03:00
|
|
|
last = (char *)tmp;
|
2001-07-24 19:11:02 +04:00
|
|
|
}
|
|
|
|
else {
|
2012-01-25 06:32:06 +04:00
|
|
|
Inc(path, end, enc);
|
2001-07-24 19:11:02 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return last;
|
|
|
|
}
|
1999-08-13 09:45:20 +04:00
|
|
|
|
2006-09-25 16:25:29 +04:00
|
|
|
static char *
|
2014-06-03 00:23:47 +04:00
|
|
|
chompdirsep(const char *path, const char *end, rb_encoding *enc)
|
2003-02-12 17:56:45 +03:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end) {
|
2003-02-12 17:56:45 +03:00
|
|
|
if (isdirsep(*path)) {
|
|
|
|
const char *last = path++;
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end && isdirsep(*path)) path++;
|
|
|
|
if (path >= end) return (char *)last;
|
2003-02-12 17:56:45 +03:00
|
|
|
}
|
|
|
|
else {
|
2012-01-25 06:32:06 +04:00
|
|
|
Inc(path, end, enc);
|
2003-02-12 17:56:45 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (char *)path;
|
|
|
|
}
|
|
|
|
|
2006-09-25 16:25:29 +04:00
|
|
|
char *
|
2014-06-03 00:23:47 +04:00
|
|
|
rb_enc_path_end(const char *path, const char *end, rb_encoding *enc)
|
2006-09-25 16:25:29 +04:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
if (path < end && isdirsep(*path)) path++;
|
|
|
|
return chompdirsep(path, end, enc);
|
2006-09-25 16:25:29 +04:00
|
|
|
}
|
|
|
|
|
2021-01-13 18:14:11 +03:00
|
|
|
static rb_encoding *
|
|
|
|
fs_enc_check(VALUE path1, VALUE path2)
|
|
|
|
{
|
|
|
|
rb_encoding *enc = rb_enc_check(path1, path2);
|
|
|
|
int encidx = rb_enc_to_index(enc);
|
|
|
|
if (encidx == ENCINDEX_US_ASCII) {
|
|
|
|
encidx = rb_enc_get_index(path1);
|
|
|
|
if (encidx == ENCINDEX_US_ASCII)
|
|
|
|
encidx = rb_enc_get_index(path2);
|
|
|
|
enc = rb_enc_from_index(encidx);
|
|
|
|
}
|
|
|
|
return enc;
|
|
|
|
}
|
|
|
|
|
2008-05-15 10:34:02 +04:00
|
|
|
#if USE_NTFS
|
|
|
|
static char *
|
2014-06-03 00:23:47 +04:00
|
|
|
ntfs_tail(const char *path, const char *end, rb_encoding *enc)
|
2008-05-15 10:34:02 +04:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end && *path == '.') path++;
|
2016-12-06 10:21:55 +03:00
|
|
|
while (path < end && !isADS(*path)) {
|
2009-05-31 18:26:40 +04:00
|
|
|
if (istrailinggarbage(*path)) {
|
2008-05-15 10:34:02 +04:00
|
|
|
const char *last = path++;
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end && istrailinggarbage(*path)) path++;
|
2016-12-06 10:21:55 +03:00
|
|
|
if (path >= end || isADS(*path)) return (char *)last;
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
|
|
|
else if (isdirsep(*path)) {
|
|
|
|
const char *last = path++;
|
2012-01-25 06:32:06 +04:00
|
|
|
while (path < end && isdirsep(*path)) path++;
|
|
|
|
if (path >= end) return (char *)last;
|
2016-12-06 10:21:55 +03:00
|
|
|
if (isADS(*path)) path++;
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
|
|
|
else {
|
2012-01-25 06:32:06 +04:00
|
|
|
Inc(path, end, enc);
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (char *)path;
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* USE_NTFS */
|
2008-05-15 10:34:02 +04:00
|
|
|
|
2003-08-23 19:44:05 +04:00
|
|
|
#define BUFCHECK(cond) do {\
|
2009-06-29 12:16:19 +04:00
|
|
|
bdiff = p - buf;\
|
2008-05-27 07:07:55 +04:00
|
|
|
if (cond) {\
|
2008-05-26 13:24:56 +04:00
|
|
|
do {buflen *= 2;} while (cond);\
|
|
|
|
rb_str_resize(result, buflen);\
|
|
|
|
buf = RSTRING_PTR(result);\
|
|
|
|
p = buf + bdiff;\
|
|
|
|
pend = buf + buflen;\
|
2003-08-23 19:44:05 +04:00
|
|
|
}\
|
|
|
|
} while (0)
|
2002-02-04 11:09:14 +03:00
|
|
|
|
2003-02-16 13:22:36 +03:00
|
|
|
#define BUFINIT() (\
|
2006-08-31 14:47:44 +04:00
|
|
|
p = buf = RSTRING_PTR(result),\
|
|
|
|
buflen = RSTRING_LEN(result),\
|
2003-02-16 13:22:36 +03:00
|
|
|
pend = p + buflen)
|
|
|
|
|
2014-12-25 10:01:22 +03:00
|
|
|
#ifdef __APPLE__
|
|
|
|
# define SKIPPATHSEP(p) ((*(p)) ? 1 : 0)
|
|
|
|
#else
|
|
|
|
# define SKIPPATHSEP(p) 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define BUFCOPY(srcptr, srclen) do { \
|
|
|
|
const int skip = SKIPPATHSEP(p); \
|
|
|
|
rb_str_set_len(result, p-buf+skip); \
|
|
|
|
BUFCHECK(bdiff + ((srclen)+skip) >= buflen); \
|
|
|
|
p += skip; \
|
|
|
|
memcpy(p, (srcptr), (srclen)); \
|
|
|
|
p += (srclen); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define WITH_ROOTDIFF(stmt) do { \
|
|
|
|
long rootdiff = root - buf; \
|
|
|
|
stmt; \
|
|
|
|
root = buf + rootdiff; \
|
|
|
|
} while (0)
|
|
|
|
|
2013-07-25 08:06:50 +04:00
|
|
|
static VALUE
|
|
|
|
copy_home_path(VALUE result, const char *dir)
|
2009-02-02 10:33:08 +03:00
|
|
|
{
|
|
|
|
char *buf;
|
2009-02-02 10:59:35 +03:00
|
|
|
#if defined DOSISH || defined __CYGWIN__
|
2012-01-25 06:32:06 +04:00
|
|
|
char *p, *bend;
|
2015-10-17 07:31:43 +03:00
|
|
|
rb_encoding *enc;
|
2009-02-02 10:59:35 +03:00
|
|
|
#endif
|
2009-02-02 10:33:08 +03:00
|
|
|
long dirlen;
|
2015-10-17 07:31:43 +03:00
|
|
|
int encidx;
|
2009-02-02 10:33:08 +03:00
|
|
|
|
2013-07-25 08:06:50 +04:00
|
|
|
dirlen = strlen(dir);
|
|
|
|
rb_str_resize(result, dirlen);
|
|
|
|
memcpy(buf = RSTRING_PTR(result), dir, dirlen);
|
2015-10-17 07:31:43 +03:00
|
|
|
encidx = rb_filesystem_encindex();
|
|
|
|
rb_enc_associate_index(result, encidx);
|
2009-02-02 10:33:08 +03:00
|
|
|
#if defined DOSISH || defined __CYGWIN__
|
2015-10-17 07:31:43 +03:00
|
|
|
enc = rb_enc_from_index(encidx);
|
2012-01-25 06:32:06 +04:00
|
|
|
for (bend = (p = buf) + dirlen; p < bend; Inc(p, bend, enc)) {
|
2009-02-02 10:33:08 +03:00
|
|
|
if (*p == '\\') {
|
|
|
|
*p = '/';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-07-25 08:06:50 +04:00
|
|
|
VALUE
|
|
|
|
rb_home_dir_of(VALUE user, VALUE result)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_PWD_H
|
2016-11-05 18:00:37 +03:00
|
|
|
struct passwd *pwPtr;
|
2016-05-08 12:51:34 +03:00
|
|
|
#else
|
|
|
|
extern char *getlogin(void);
|
|
|
|
const char *pwPtr = 0;
|
|
|
|
# define endpwent() ((void)0)
|
2016-11-05 18:00:37 +03:00
|
|
|
#endif
|
|
|
|
const char *dir, *username = RSTRING_PTR(user);
|
|
|
|
rb_encoding *enc = rb_enc_get(user);
|
|
|
|
#if defined _WIN32
|
|
|
|
rb_encoding *fsenc = rb_utf8_encoding();
|
|
|
|
#else
|
|
|
|
rb_encoding *fsenc = rb_filesystem_encoding();
|
|
|
|
#endif
|
|
|
|
if (enc != fsenc) {
|
|
|
|
dir = username = RSTRING_PTR(rb_str_conv_enc(user, enc, fsenc));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_PWD_H
|
|
|
|
pwPtr = getpwnam(username);
|
|
|
|
#else
|
2016-05-08 12:51:34 +03:00
|
|
|
if (strcasecmp(username, getlogin()) == 0)
|
|
|
|
dir = pwPtr = getenv("HOME");
|
|
|
|
#endif
|
2013-07-25 08:06:50 +04:00
|
|
|
if (!pwPtr) {
|
|
|
|
endpwent();
|
|
|
|
rb_raise(rb_eArgError, "user %"PRIsVALUE" doesn't exist", user);
|
|
|
|
}
|
2016-05-08 12:51:34 +03:00
|
|
|
#ifdef HAVE_PWD_H
|
|
|
|
dir = pwPtr->pw_dir;
|
2013-07-25 08:06:50 +04:00
|
|
|
#endif
|
2016-05-08 12:51:34 +03:00
|
|
|
copy_home_path(result, dir);
|
|
|
|
endpwent();
|
2013-07-25 08:06:50 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-01-31 01:50:37 +03:00
|
|
|
#ifndef _WIN32 /* this encompasses rb_file_expand_path_internal */
|
2013-07-25 08:06:50 +04:00
|
|
|
VALUE
|
|
|
|
rb_default_home_dir(VALUE result)
|
|
|
|
{
|
|
|
|
const char *dir = getenv("HOME");
|
2016-11-26 14:37:01 +03:00
|
|
|
|
|
|
|
#if defined HAVE_PWD_H
|
|
|
|
if (!dir) {
|
2020-04-15 14:29:16 +03:00
|
|
|
/* We'll look up the user's default home dir in the password db by
|
|
|
|
* login name, if possible, and failing that will fall back to looking
|
|
|
|
* the information up by uid (as would be needed for processes that
|
|
|
|
* are not a descendant of login(1) or a work-alike).
|
|
|
|
*
|
|
|
|
* While the lookup by uid is more likely to succeed (since we always
|
|
|
|
* have a uid, but may or may not have a login name), we prefer first
|
|
|
|
* looking up by name to accommodate the possibility of multiple login
|
|
|
|
* names (each with its own record in the password database, so each
|
|
|
|
* with a potentially different home directory) being mapped to the
|
|
|
|
* same uid (as explicitly allowed for by POSIX; see getlogin(3posix)).
|
|
|
|
*/
|
|
|
|
VALUE login_name = rb_getlogin();
|
|
|
|
|
|
|
|
# if !defined(HAVE_GETPWUID_R) && !defined(HAVE_GETPWUID)
|
|
|
|
/* This is a corner case, but for backward compatibility reasons we
|
|
|
|
* want to emit this error if neither the lookup by login name nor
|
|
|
|
* lookup by getuid() has a chance of succeeding.
|
|
|
|
*/
|
|
|
|
if (NIL_P(login_name)) {
|
|
|
|
rb_raise(rb_eArgError, "couldn't find login name -- expanding `~'");
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif /* !defined(HAVE_GETPWUID_R) && !defined(HAVE_GETPWUID) */
|
2020-04-15 14:29:16 +03:00
|
|
|
|
|
|
|
VALUE pw_dir = rb_getpwdirnam_for_login(login_name);
|
|
|
|
if (NIL_P(pw_dir)) {
|
|
|
|
pw_dir = rb_getpwdiruid();
|
|
|
|
if (NIL_P(pw_dir)) {
|
|
|
|
rb_raise(rb_eArgError, "couldn't find home for uid `%ld'", (long)getuid());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* found it */
|
|
|
|
copy_home_path(result, RSTRING_PTR(pw_dir));
|
|
|
|
rb_str_resize(pw_dir, 0);
|
|
|
|
return result;
|
2016-11-26 14:37:01 +03:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* defined HAVE_PWD_H */
|
2013-07-25 08:06:50 +04:00
|
|
|
if (!dir) {
|
|
|
|
rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'");
|
|
|
|
}
|
|
|
|
return copy_home_path(result, dir);
|
|
|
|
}
|
|
|
|
|
2016-06-12 03:24:36 +03:00
|
|
|
static VALUE
|
|
|
|
ospath_new(const char *ptr, long len, rb_encoding *fsenc)
|
|
|
|
{
|
|
|
|
#if NORMALIZE_UTF8PATH
|
|
|
|
VALUE path = rb_str_normalize_ospath(ptr, len);
|
|
|
|
rb_enc_associate(path, fsenc);
|
|
|
|
return path;
|
|
|
|
#else
|
|
|
|
return rb_enc_str_new(ptr, len, fsenc);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-01-25 06:32:06 +04:00
|
|
|
static char *
|
|
|
|
append_fspath(VALUE result, VALUE fname, char *dir, rb_encoding **enc, rb_encoding *fsenc)
|
|
|
|
{
|
|
|
|
char *buf, *cwdp = dir;
|
|
|
|
VALUE dirname = Qnil;
|
|
|
|
size_t dirlen = strlen(dir), buflen = rb_str_capacity(result);
|
|
|
|
|
2016-06-12 03:24:36 +03:00
|
|
|
if (NORMALIZE_UTF8PATH || *enc != fsenc) {
|
2021-01-13 18:14:11 +03:00
|
|
|
rb_encoding *direnc = fs_enc_check(fname, dirname = ospath_new(dir, dirlen, fsenc));
|
2012-01-25 06:32:06 +04:00
|
|
|
if (direnc != fsenc) {
|
|
|
|
dirname = rb_str_conv_enc(dirname, fsenc, direnc);
|
|
|
|
RSTRING_GETMEM(dirname, cwdp, dirlen);
|
|
|
|
}
|
2016-06-12 03:24:36 +03:00
|
|
|
else if (NORMALIZE_UTF8PATH) {
|
|
|
|
RSTRING_GETMEM(dirname, cwdp, dirlen);
|
|
|
|
}
|
2012-01-25 06:32:06 +04:00
|
|
|
*enc = direnc;
|
|
|
|
}
|
|
|
|
do {buflen *= 2;} while (dirlen > buflen);
|
|
|
|
rb_str_resize(result, buflen);
|
|
|
|
buf = RSTRING_PTR(result);
|
|
|
|
memcpy(buf, cwdp, dirlen);
|
|
|
|
xfree(dir);
|
|
|
|
if (!NIL_P(dirname)) rb_str_resize(dirname, 0);
|
2012-01-30 07:31:58 +04:00
|
|
|
rb_enc_associate(result, *enc);
|
2012-01-25 06:32:06 +04:00
|
|
|
return buf + dirlen;
|
|
|
|
}
|
|
|
|
|
2012-08-24 07:44:56 +04:00
|
|
|
VALUE
|
|
|
|
rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result)
|
2003-02-12 17:56:45 +03:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *s, *b, *fend;
|
2008-04-20 10:19:28 +04:00
|
|
|
char *buf, *p, *pend, *root;
|
2012-01-25 06:32:06 +04:00
|
|
|
size_t buflen, bdiff;
|
|
|
|
rb_encoding *enc, *fsenc = rb_filesystem_encoding();
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2003-07-23 10:48:52 +04:00
|
|
|
s = StringValuePtr(fname);
|
2012-01-25 06:32:06 +04:00
|
|
|
fend = s + RSTRING_LEN(fname);
|
|
|
|
enc = rb_enc_get(fname);
|
2003-02-16 13:22:36 +03:00
|
|
|
BUFINIT();
|
2002-02-04 11:09:14 +03:00
|
|
|
|
2008-08-28 07:51:22 +04:00
|
|
|
if (s[0] == '~' && abs_mode == 0) { /* execute only if NOT absolute_path() */
|
2010-07-30 03:51:53 +04:00
|
|
|
long userlen = 0;
|
1999-08-13 09:45:20 +04:00
|
|
|
if (isdirsep(s[1]) || s[1] == '\0') {
|
2009-02-02 10:33:08 +03:00
|
|
|
buf = 0;
|
2010-07-30 11:06:51 +04:00
|
|
|
b = 0;
|
2009-02-02 10:33:08 +03:00
|
|
|
rb_str_set_len(result, 0);
|
|
|
|
if (*++s) ++s;
|
2013-07-25 08:06:50 +04:00
|
|
|
rb_default_home_dir(result);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
else {
|
2012-01-25 06:32:06 +04:00
|
|
|
s = nextdirsep(b = s, fend, enc);
|
2013-07-25 20:33:57 +04:00
|
|
|
b++; /* b[0] is '~' */
|
2010-07-30 03:51:53 +04:00
|
|
|
userlen = s - b;
|
|
|
|
BUFCHECK(bdiff + userlen >= buflen);
|
|
|
|
memcpy(p, b, userlen);
|
2013-07-25 12:17:55 +04:00
|
|
|
ENC_CODERANGE_CLEAR(result);
|
2010-07-30 03:51:53 +04:00
|
|
|
rb_str_set_len(result, userlen);
|
2013-07-25 08:06:50 +04:00
|
|
|
rb_enc_associate(result, enc);
|
|
|
|
rb_home_dir_of(result, result);
|
2009-02-02 10:33:08 +03:00
|
|
|
buf = p + 1;
|
2010-07-30 03:51:53 +04:00
|
|
|
p += userlen;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2010-07-30 03:51:53 +04:00
|
|
|
if (!rb_is_absolute_path(RSTRING_PTR(result))) {
|
|
|
|
if (userlen) {
|
2013-07-24 12:38:01 +04:00
|
|
|
rb_enc_raise(enc, rb_eArgError, "non-absolute home of %.*s%.0"PRIsVALUE,
|
|
|
|
(int)userlen, b, fname);
|
2010-07-30 03:51:53 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_raise(rb_eArgError, "non-absolute home");
|
|
|
|
}
|
|
|
|
}
|
2009-02-02 10:33:08 +03:00
|
|
|
BUFINIT();
|
|
|
|
p = pend;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2003-02-12 17:56:45 +03:00
|
|
|
#ifdef DOSISH_DRIVE_LETTER
|
1999-08-13 09:45:20 +04:00
|
|
|
/* skip drive letter */
|
2003-01-06 12:44:15 +03:00
|
|
|
else if (has_drive_letter(s)) {
|
|
|
|
if (isdirsep(s[2])) {
|
|
|
|
/* specified drive letter, and full path */
|
|
|
|
/* skip drive letter */
|
2003-08-23 20:06:25 +04:00
|
|
|
BUFCHECK(bdiff + 2 >= buflen);
|
2003-02-16 13:22:36 +03:00
|
|
|
memcpy(p, s, 2);
|
|
|
|
p += 2;
|
|
|
|
s += 2;
|
2009-06-29 12:14:39 +04:00
|
|
|
rb_enc_copy(result, fname);
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* specified drive, but not full path */
|
|
|
|
int same = 0;
|
2010-08-02 07:25:12 +04:00
|
|
|
if (!NIL_P(dname) && !not_same_drive(dname, s[0])) {
|
2012-08-24 07:44:56 +04:00
|
|
|
rb_file_expand_path_internal(dname, Qnil, abs_mode, long_name, result);
|
2003-02-16 13:22:36 +03:00
|
|
|
BUFINIT();
|
|
|
|
if (has_drive_letter(p) && TOLOWER(p[0]) == TOLOWER(s[0])) {
|
2003-01-06 12:44:15 +03:00
|
|
|
/* ok, same drive */
|
|
|
|
same = 1;
|
|
|
|
}
|
|
|
|
}
|
2003-02-12 17:56:45 +03:00
|
|
|
if (!same) {
|
2012-01-25 06:32:06 +04:00
|
|
|
char *e = append_fspath(result, fname, getcwdofdrv(*s), &enc, fsenc);
|
|
|
|
BUFINIT();
|
|
|
|
p = e;
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
2012-01-25 06:32:06 +04:00
|
|
|
else {
|
2021-01-13 18:14:11 +03:00
|
|
|
rb_enc_associate(result, enc = fs_enc_check(result, fname));
|
2012-01-25 06:32:06 +04:00
|
|
|
p = pend;
|
|
|
|
}
|
|
|
|
p = chompdirsep(skiproot(buf, p, enc), p, enc);
|
2003-02-12 17:56:45 +03:00
|
|
|
s += 2;
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* DOSISH_DRIVE_LETTER */
|
2010-03-13 04:34:38 +03:00
|
|
|
else if (!rb_is_absolute_path(s)) {
|
2000-10-13 13:01:58 +04:00
|
|
|
if (!NIL_P(dname)) {
|
2012-08-24 07:44:56 +04:00
|
|
|
rb_file_expand_path_internal(dname, Qnil, abs_mode, long_name, result);
|
2021-01-13 18:14:11 +03:00
|
|
|
rb_enc_associate(result, fs_enc_check(result, fname));
|
2012-01-25 06:32:06 +04:00
|
|
|
BUFINIT();
|
|
|
|
p = pend;
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
else {
|
2017-11-26 04:36:33 +03:00
|
|
|
char *e = append_fspath(result, fname, ruby_getcwd(), &enc, fsenc);
|
2012-01-25 06:32:06 +04:00
|
|
|
BUFINIT();
|
|
|
|
p = e;
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
2003-07-23 18:09:52 +04:00
|
|
|
#if defined DOSISH || defined __CYGWIN__
|
2003-02-16 13:22:36 +03:00
|
|
|
if (isdirsep(*s)) {
|
|
|
|
/* specified full path, but not drive letter nor UNC */
|
2003-02-20 12:11:05 +03:00
|
|
|
/* we need to get the drive letter or UNC share name */
|
2012-01-25 06:32:06 +04:00
|
|
|
p = skipprefix(buf, p, enc);
|
2003-02-16 13:22:36 +03:00
|
|
|
}
|
|
|
|
else
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* defined DOSISH || defined __CYGWIN__ */
|
2012-01-25 06:32:06 +04:00
|
|
|
p = chompdirsep(skiproot(buf, p, enc), p, enc);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2000-01-17 11:37:53 +03:00
|
|
|
else {
|
2010-03-24 04:25:02 +03:00
|
|
|
size_t len;
|
2003-02-14 19:09:07 +03:00
|
|
|
b = s;
|
|
|
|
do s++; while (isdirsep(*s));
|
2010-03-24 04:25:02 +03:00
|
|
|
len = s - b;
|
|
|
|
p = buf + len;
|
2003-08-23 20:06:25 +04:00
|
|
|
BUFCHECK(bdiff >= buflen);
|
2010-03-24 04:25:02 +03:00
|
|
|
memset(buf, '/', len);
|
|
|
|
rb_str_set_len(result, len);
|
2021-01-13 18:14:11 +03:00
|
|
|
rb_enc_associate(result, fs_enc_check(result, fname));
|
1999-09-16 13:40:33 +04:00
|
|
|
}
|
2003-02-17 07:27:45 +03:00
|
|
|
if (p > buf && p[-1] == '/')
|
|
|
|
--p;
|
2008-05-26 12:25:44 +04:00
|
|
|
else {
|
2010-04-30 07:06:43 +04:00
|
|
|
rb_str_set_len(result, p-buf);
|
2008-09-07 02:15:18 +04:00
|
|
|
BUFCHECK(bdiff + 1 >= buflen);
|
2003-02-17 07:27:45 +03:00
|
|
|
*p = '/';
|
2008-05-26 12:25:44 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2010-04-30 07:06:43 +04:00
|
|
|
rb_str_set_len(result, p-buf+1);
|
2008-08-28 19:03:38 +04:00
|
|
|
BUFCHECK(bdiff + 1 >= buflen);
|
2003-02-20 12:11:05 +03:00
|
|
|
p[1] = 0;
|
2012-01-25 06:32:06 +04:00
|
|
|
root = skipprefix(buf, p+1, enc);
|
2003-02-20 12:11:05 +03:00
|
|
|
|
2001-07-31 02:41:59 +04:00
|
|
|
b = s;
|
2001-07-27 13:12:12 +04:00
|
|
|
while (*s) {
|
1998-01-16 15:13:05 +03:00
|
|
|
switch (*s) {
|
|
|
|
case '.':
|
2001-07-31 02:41:59 +04:00
|
|
|
if (b == s++) { /* beginning of path element */
|
|
|
|
switch (*s) {
|
|
|
|
case '\0':
|
|
|
|
b = s;
|
|
|
|
break;
|
1998-01-16 15:13:05 +03:00
|
|
|
case '.':
|
2001-07-16 08:22:46 +04:00
|
|
|
if (*(s+1) == '\0' || isdirsep(*(s+1))) {
|
1998-01-16 15:13:05 +03:00
|
|
|
/* We must go back to the parent */
|
2008-04-20 10:19:28 +04:00
|
|
|
char *n;
|
2001-07-31 02:41:59 +04:00
|
|
|
*p = '\0';
|
2012-01-25 06:32:06 +04:00
|
|
|
if (!(n = strrdirsep(root, p, enc))) {
|
2001-07-31 02:41:59 +04:00
|
|
|
*p = '/';
|
|
|
|
}
|
|
|
|
else {
|
2008-04-20 10:19:28 +04:00
|
|
|
p = n;
|
2001-07-31 02:41:59 +04:00
|
|
|
}
|
|
|
|
b = ++s;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2008-05-15 10:34:02 +04:00
|
|
|
#if USE_NTFS
|
|
|
|
else {
|
2009-05-31 18:26:40 +04:00
|
|
|
do ++s; while (istrailinggarbage(*s));
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* USE_NTFS */
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
|
|
|
case '/':
|
2003-07-23 18:09:52 +04:00
|
|
|
#if defined DOSISH || defined __CYGWIN__
|
1999-08-13 09:45:20 +04:00
|
|
|
case '\\':
|
|
|
|
#endif
|
2001-07-31 02:41:59 +04:00
|
|
|
b = ++s;
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
|
|
|
default:
|
2001-07-31 02:41:59 +04:00
|
|
|
/* ordinary path element, beginning don't move */
|
|
|
|
break;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
2008-05-15 10:34:02 +04:00
|
|
|
#if USE_NTFS
|
|
|
|
else {
|
|
|
|
--s;
|
|
|
|
case ' ': {
|
|
|
|
const char *e = s;
|
2012-01-25 06:32:06 +04:00
|
|
|
while (s < fend && istrailinggarbage(*s)) s++;
|
2016-12-06 10:21:55 +03:00
|
|
|
if (s >= fend) {
|
2008-05-15 10:34:02 +04:00
|
|
|
s = e;
|
|
|
|
goto endpath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* USE_NTFS */
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
|
|
|
case '/':
|
2003-07-23 18:09:52 +04:00
|
|
|
#if defined DOSISH || defined __CYGWIN__
|
1999-08-13 09:45:20 +04:00
|
|
|
case '\\':
|
|
|
|
#endif
|
2001-07-31 02:41:59 +04:00
|
|
|
if (s > b) {
|
2014-12-25 10:01:22 +03:00
|
|
|
WITH_ROOTDIFF(BUFCOPY(b, s-b));
|
2001-07-31 02:41:59 +04:00
|
|
|
*p = '/';
|
|
|
|
}
|
|
|
|
b = ++s;
|
|
|
|
break;
|
1998-01-16 15:13:05 +03:00
|
|
|
default:
|
2014-12-25 10:01:22 +03:00
|
|
|
#ifdef __APPLE__
|
|
|
|
{
|
|
|
|
int n = ignored_char_p(s, fend, enc);
|
|
|
|
if (n) {
|
|
|
|
if (s > b) {
|
|
|
|
WITH_ROOTDIFF(BUFCOPY(b, s-b));
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
b = s += n;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* __APPLE__ */
|
2012-01-25 06:32:06 +04:00
|
|
|
Inc(s, fend, enc);
|
2001-07-31 02:41:59 +04:00
|
|
|
break;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
2001-07-16 08:22:46 +04:00
|
|
|
|
2001-07-31 02:41:59 +04:00
|
|
|
if (s > b) {
|
2008-05-15 10:34:02 +04:00
|
|
|
#if USE_NTFS
|
2016-12-06 10:21:55 +03:00
|
|
|
# if USE_NTFS_ADS
|
2009-02-18 06:01:03 +03:00
|
|
|
static const char prime[] = ":$DATA";
|
|
|
|
enum {prime_len = sizeof(prime) -1};
|
2016-12-06 10:21:55 +03:00
|
|
|
# endif
|
2008-05-15 10:34:02 +04:00
|
|
|
endpath:
|
2016-12-06 10:21:55 +03:00
|
|
|
# if USE_NTFS_ADS
|
2009-02-18 06:01:03 +03:00
|
|
|
if (s > b + prime_len && strncasecmp(s - prime_len, prime, prime_len) == 0) {
|
2008-05-15 10:34:02 +04:00
|
|
|
/* alias of stream */
|
|
|
|
/* get rid of a bug of x64 VC++ */
|
2016-12-06 10:21:55 +03:00
|
|
|
if (isADS(*(s - (prime_len+1)))) {
|
2009-02-18 06:01:03 +03:00
|
|
|
s -= prime_len + 1; /* prime */
|
|
|
|
}
|
|
|
|
else if (memchr(b, ':', s - prime_len - b)) {
|
|
|
|
s -= prime_len; /* alternative */
|
|
|
|
}
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif /* USE_NTFS_ADS */
|
|
|
|
#endif /* USE_NTFS */
|
2014-12-25 10:01:22 +03:00
|
|
|
BUFCOPY(b, s-b);
|
2012-01-25 06:32:06 +04:00
|
|
|
rb_str_set_len(result, p-buf);
|
2001-07-31 02:41:59 +04:00
|
|
|
}
|
2012-01-25 06:32:06 +04:00
|
|
|
if (p == skiproot(buf, p + !!*p, enc) - 1) p++;
|
2008-05-15 10:34:02 +04:00
|
|
|
|
2010-05-26 15:04:43 +04:00
|
|
|
#if USE_NTFS
|
2008-05-15 10:34:02 +04:00
|
|
|
*p = '\0';
|
2012-01-25 06:32:06 +04:00
|
|
|
if ((s = strrdirsep(b = buf, p, enc)) != 0 && !strpbrk(s, "*?")) {
|
|
|
|
VALUE tmp, v;
|
2008-05-15 10:34:02 +04:00
|
|
|
size_t len;
|
2015-10-17 07:31:43 +03:00
|
|
|
int encidx;
|
2012-01-25 06:32:06 +04:00
|
|
|
WCHAR *wstr;
|
|
|
|
WIN32_FIND_DATAW wfd;
|
2010-12-26 16:24:17 +03:00
|
|
|
HANDLE h;
|
2008-05-15 10:34:02 +04:00
|
|
|
#ifdef __CYGWIN__
|
2010-12-26 16:24:17 +03:00
|
|
|
#ifdef HAVE_CYGWIN_CONV_PATH
|
|
|
|
char *w32buf = NULL;
|
|
|
|
const int flags = CCP_POSIX_TO_WIN_A | CCP_RELATIVE;
|
|
|
|
#else
|
|
|
|
char w32buf[MAXPATHLEN];
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* HAVE_CYGWIN_CONV_PATH */
|
2010-12-26 16:24:17 +03:00
|
|
|
const char *path;
|
2010-11-11 15:24:41 +03:00
|
|
|
ssize_t bufsize;
|
2008-05-17 18:54:07 +04:00
|
|
|
int lnk_added = 0, is_symlink = 0;
|
2008-05-15 10:34:02 +04:00
|
|
|
struct stat st;
|
2008-06-14 11:56:06 +04:00
|
|
|
p = (char *)s;
|
2010-11-11 15:24:41 +03:00
|
|
|
len = strlen(p);
|
2017-10-04 02:47:53 +03:00
|
|
|
if (lstat_without_gvl(buf, &st) == 0 && S_ISLNK(st.st_mode)) {
|
2008-05-17 18:54:07 +04:00
|
|
|
is_symlink = 1;
|
2010-11-11 15:24:41 +03:00
|
|
|
if (len > 4 && STRCASECMP(p + len - 4, ".lnk") != 0) {
|
|
|
|
lnk_added = 1;
|
|
|
|
}
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
2010-12-26 16:24:17 +03:00
|
|
|
path = *buf ? buf : "/";
|
2010-11-11 15:24:41 +03:00
|
|
|
#ifdef HAVE_CYGWIN_CONV_PATH
|
|
|
|
bufsize = cygwin_conv_path(flags, path, NULL, 0);
|
|
|
|
if (bufsize > 0) {
|
|
|
|
bufsize += len;
|
|
|
|
if (lnk_added) bufsize += 4;
|
|
|
|
w32buf = ALLOCA_N(char, bufsize);
|
|
|
|
if (cygwin_conv_path(flags, path, w32buf, bufsize) == 0) {
|
|
|
|
b = w32buf;
|
|
|
|
}
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#else /* !HAVE_CYGWIN_CONV_PATH */
|
2010-11-11 15:24:41 +03:00
|
|
|
bufsize = MAXPATHLEN;
|
|
|
|
if (cygwin_conv_to_win32_path(path, w32buf) == 0) {
|
2008-05-15 10:34:02 +04:00
|
|
|
b = w32buf;
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* !HAVE_CYGWIN_CONV_PATH */
|
2008-05-17 18:54:07 +04:00
|
|
|
if (is_symlink && b == w32buf) {
|
2008-06-03 11:06:23 +04:00
|
|
|
*p = '\\';
|
2010-11-11 15:24:41 +03:00
|
|
|
strlcat(w32buf, p, bufsize);
|
|
|
|
if (lnk_added) {
|
|
|
|
strlcat(w32buf, ".lnk", bufsize);
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
|
|
|
}
|
2010-11-11 15:24:41 +03:00
|
|
|
else {
|
|
|
|
lnk_added = 0;
|
|
|
|
}
|
2008-06-03 11:06:23 +04:00
|
|
|
*p = '/';
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* __CYGWIN__ */
|
2012-01-25 06:32:06 +04:00
|
|
|
rb_str_set_len(result, p - buf + strlen(p));
|
2015-10-19 15:10:14 +03:00
|
|
|
encidx = ENCODING_GET(result);
|
2012-01-25 06:32:06 +04:00
|
|
|
tmp = result;
|
2022-05-01 17:13:59 +03:00
|
|
|
if (encidx != ENCINDEX_UTF_8 && !is_ascii_string(result)) {
|
2012-01-25 06:32:06 +04:00
|
|
|
tmp = rb_str_encode_ospath(result);
|
|
|
|
}
|
|
|
|
len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, NULL, 0);
|
|
|
|
wstr = ALLOCV_N(WCHAR, v, len);
|
|
|
|
MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, wstr, len);
|
2015-10-17 07:31:43 +03:00
|
|
|
if (tmp != result) rb_str_set_len(tmp, 0);
|
2012-01-25 06:32:06 +04:00
|
|
|
h = FindFirstFileW(wstr, &wfd);
|
|
|
|
ALLOCV_END(v);
|
2008-05-15 10:34:02 +04:00
|
|
|
if (h != INVALID_HANDLE_VALUE) {
|
2012-01-25 06:32:06 +04:00
|
|
|
size_t wlen;
|
2008-05-15 10:34:02 +04:00
|
|
|
FindClose(h);
|
2012-01-25 06:32:06 +04:00
|
|
|
len = lstrlenW(wfd.cFileName);
|
2008-05-15 10:34:02 +04:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
if (lnk_added && len > 4 &&
|
2012-03-02 11:37:13 +04:00
|
|
|
wcscasecmp(wfd.cFileName + len - 4, L".lnk") == 0) {
|
2012-01-25 06:32:06 +04:00
|
|
|
wfd.cFileName[len -= 4] = L'\0';
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
2008-06-03 11:06:23 +04:00
|
|
|
#else
|
2008-06-14 11:56:06 +04:00
|
|
|
p = (char *)s;
|
2008-05-15 10:34:02 +04:00
|
|
|
#endif
|
2008-06-03 11:06:23 +04:00
|
|
|
++p;
|
2012-01-25 06:32:06 +04:00
|
|
|
wlen = (int)len;
|
|
|
|
len = WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, NULL, 0, NULL, NULL);
|
2015-10-17 07:55:47 +03:00
|
|
|
if (tmp == result) {
|
2012-01-25 06:32:06 +04:00
|
|
|
BUFCHECK(bdiff + len >= buflen);
|
2015-10-17 07:55:47 +03:00
|
|
|
WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, p, len + 1, NULL, NULL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_str_modify_expand(tmp, len);
|
|
|
|
WideCharToMultiByte(CP_UTF8, 0, wfd.cFileName, wlen, RSTRING_PTR(tmp), len + 1, NULL, NULL);
|
|
|
|
rb_str_cat_conv_enc_opts(result, bdiff, RSTRING_PTR(tmp), len,
|
|
|
|
rb_utf8_encoding(), 0, Qnil);
|
|
|
|
BUFINIT();
|
2012-01-25 06:32:06 +04:00
|
|
|
rb_str_resize(tmp, 0);
|
|
|
|
}
|
2008-05-27 07:07:55 +04:00
|
|
|
p += len;
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
2008-06-03 11:06:23 +04:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
else {
|
|
|
|
p += strlen(p);
|
|
|
|
}
|
|
|
|
#endif
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* USE_NTFS */
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-05-27 07:07:55 +04:00
|
|
|
rb_str_set_len(result, p - buf);
|
2008-04-11 22:13:40 +04:00
|
|
|
rb_enc_check(fname, result);
|
2011-11-01 12:17:59 +04:00
|
|
|
ENC_CODERANGE_CLEAR(result);
|
2002-02-04 11:09:14 +03:00
|
|
|
return result;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* !_WIN32 (this ifdef started above rb_default_home_dir) */
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2022-04-12 16:18:41 +03:00
|
|
|
#define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, 1)
|
2010-03-02 08:29:27 +03:00
|
|
|
|
2014-06-12 08:09:41 +04:00
|
|
|
static VALUE
|
|
|
|
str_shrink(VALUE str)
|
|
|
|
{
|
|
|
|
rb_str_resize(str, RSTRING_LEN(str));
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define expand_path(fname, dname, abs_mode, long_name, result) \
|
|
|
|
str_shrink(rb_file_expand_path_internal(fname, dname, abs_mode, long_name, result))
|
|
|
|
|
2010-03-02 08:29:27 +03:00
|
|
|
#define check_expand_path_args(fname, dname) \
|
2010-12-13 06:01:12 +03:00
|
|
|
(((fname) = rb_get_path(fname)), \
|
|
|
|
(void)(NIL_P(dname) ? (dname) : ((dname) = rb_get_path(dname))))
|
2010-03-02 08:29:27 +03:00
|
|
|
|
|
|
|
static VALUE
|
|
|
|
file_expand_path_1(VALUE fname)
|
|
|
|
{
|
2012-08-24 07:44:56 +04:00
|
|
|
return rb_file_expand_path_internal(fname, Qnil, 0, 0, EXPAND_PATH_BUFFER());
|
2010-03-02 08:29:27 +03:00
|
|
|
}
|
|
|
|
|
2003-02-20 12:11:05 +03:00
|
|
|
VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_expand_path(VALUE fname, VALUE dname)
|
2003-02-20 12:11:05 +03:00
|
|
|
{
|
2010-03-02 08:29:27 +03:00
|
|
|
check_expand_path_args(fname, dname);
|
2014-06-12 08:09:41 +04:00
|
|
|
return expand_path(fname, dname, 0, 1, EXPAND_PATH_BUFFER());
|
2012-08-24 07:44:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_file_expand_path_fast(VALUE fname, VALUE dname)
|
|
|
|
{
|
2014-06-12 08:09:41 +04:00
|
|
|
return expand_path(fname, dname, 0, 0, EXPAND_PATH_BUFFER());
|
2003-02-20 12:11:05 +03:00
|
|
|
}
|
|
|
|
|
2019-08-29 05:47:20 +03:00
|
|
|
VALUE
|
|
|
|
rb_file_s_expand_path(int argc, const VALUE *argv)
|
|
|
|
{
|
|
|
|
rb_check_arity(argc, 1, 2);
|
|
|
|
return rb_file_expand_path(argv[0], argc > 1 ? argv[1] : Qnil);
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.expand_path(file_name [, dir_string] ) -> abs_file_name
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Converts a pathname to an absolute pathname. Relative paths are
|
|
|
|
* referenced from the current working directory of the process unless
|
2013-10-23 06:44:06 +04:00
|
|
|
* +dir_string+ is given, in which case it will be used as the
|
2003-12-21 10:28:54 +03:00
|
|
|
* starting point. The given pathname may start with a
|
|
|
|
* ``<code>~</code>'', which expands to the process owner's home
|
2013-10-23 06:44:06 +04:00
|
|
|
* directory (the environment variable +HOME+ must be set
|
2003-12-21 10:28:54 +03:00
|
|
|
* correctly). ``<code>~</code><i>user</i>'' expands to the named
|
|
|
|
* user's home directory.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.expand_path("~oracle/bin") #=> "/home/oracle/bin"
|
2013-10-22 11:59:23 +04:00
|
|
|
*
|
2013-10-23 06:44:06 +04:00
|
|
|
* A simple example of using +dir_string+ is as follows.
|
2013-10-22 11:59:23 +04:00
|
|
|
* File.expand_path("ruby", "/usr/bin") #=> "/usr/bin/ruby"
|
|
|
|
*
|
|
|
|
* A more complex example which also resolves parent directory is as follows.
|
|
|
|
* Suppose we are in bin/mygem and want the absolute path of lib/mygem.rb.
|
|
|
|
*
|
|
|
|
* File.expand_path("../../lib/mygem.rb", __FILE__)
|
|
|
|
* #=> ".../path/to/project/lib/mygem.rb"
|
|
|
|
*
|
|
|
|
* So first it resolves the parent of __FILE__, that is bin/, then go to the
|
|
|
|
* parent, the root of the project and appends +lib/mygem.rb+.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2019-08-29 05:47:20 +03:00
|
|
|
static VALUE
|
|
|
|
s_expand_path(int c, const VALUE * v, VALUE _)
|
2003-02-12 17:56:45 +03:00
|
|
|
{
|
2019-08-29 05:47:20 +03:00
|
|
|
return rb_file_s_expand_path(c, v);
|
2003-02-12 17:56:45 +03:00
|
|
|
}
|
|
|
|
|
2008-08-28 07:51:22 +04:00
|
|
|
VALUE
|
|
|
|
rb_file_absolute_path(VALUE fname, VALUE dname)
|
|
|
|
{
|
2010-03-02 08:29:27 +03:00
|
|
|
check_expand_path_args(fname, dname);
|
2014-06-12 08:09:41 +04:00
|
|
|
return expand_path(fname, dname, 1, 1, EXPAND_PATH_BUFFER());
|
2008-08-28 07:51:22 +04:00
|
|
|
}
|
|
|
|
|
2019-08-29 05:47:20 +03:00
|
|
|
VALUE
|
|
|
|
rb_file_s_absolute_path(int argc, const VALUE *argv)
|
|
|
|
{
|
|
|
|
rb_check_arity(argc, 1, 2);
|
|
|
|
return rb_file_absolute_path(argv[0], argc > 1 ? argv[1] : Qnil);
|
|
|
|
}
|
|
|
|
|
2008-08-28 07:51:22 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.absolute_path(file_name [, dir_string] ) -> abs_file_name
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2008-08-28 07:51:22 +04:00
|
|
|
* Converts a pathname to an absolute pathname. Relative paths are
|
|
|
|
* referenced from the current working directory of the process unless
|
|
|
|
* <i>dir_string</i> is given, in which case it will be used as the
|
|
|
|
* starting point. If the given pathname starts with a ``<code>~</code>''
|
|
|
|
* it is NOT expanded, it is treated as a normal directory name.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2008-08-28 07:51:22 +04:00
|
|
|
* File.absolute_path("~oracle/bin") #=> "<relative_path>/~oracle/bin"
|
|
|
|
*/
|
|
|
|
|
2019-08-29 05:47:20 +03:00
|
|
|
static VALUE
|
|
|
|
s_absolute_path(int c, const VALUE * v, VALUE _)
|
2008-08-28 07:51:22 +04:00
|
|
|
{
|
2019-08-29 05:47:20 +03:00
|
|
|
return rb_file_s_absolute_path(c, v);
|
2008-08-28 07:51:22 +04:00
|
|
|
}
|
|
|
|
|
2019-09-05 14:00:50 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* File.absolute_path?(file_name) -> true or false
|
|
|
|
*
|
|
|
|
* Returns <code>true</code> if +file_name+ is an absolute path, and
|
|
|
|
* <code>false</code> otherwise.
|
|
|
|
*
|
|
|
|
* File.absolute_path?("c:/foo") #=> false (on Linux), true (on Windows)
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
s_absolute_path_p(VALUE klass, VALUE fname)
|
|
|
|
{
|
|
|
|
VALUE path = rb_get_path(fname);
|
|
|
|
|
|
|
|
if (!rb_is_absolute_path(RSTRING_PTR(path))) return Qfalse;
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
2017-09-21 10:29:16 +03:00
|
|
|
enum rb_realpath_mode {
|
|
|
|
RB_REALPATH_CHECK,
|
|
|
|
RB_REALPATH_DIR,
|
|
|
|
RB_REALPATH_STRICT,
|
|
|
|
RB_REALPATH_MODE_MAX
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2018-02-28 08:43:53 +03:00
|
|
|
realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE fallback,
|
2017-09-21 10:29:16 +03:00
|
|
|
VALUE loopcheck, enum rb_realpath_mode mode, int last)
|
2010-01-12 03:32:22 +03:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *pend = unresolved + strlen(unresolved);
|
|
|
|
rb_encoding *enc = rb_enc_get(*resolvedp);
|
2010-03-15 01:41:04 +03:00
|
|
|
ID resolving;
|
|
|
|
CONST_ID(resolving, "resolving");
|
2012-01-25 06:32:06 +04:00
|
|
|
while (unresolved < pend) {
|
|
|
|
const char *testname = unresolved;
|
|
|
|
const char *unresolved_firstsep = rb_enc_path_next(unresolved, pend, enc);
|
|
|
|
long testnamelen = unresolved_firstsep - unresolved;
|
|
|
|
const char *unresolved_nextname = unresolved_firstsep;
|
|
|
|
while (unresolved_nextname < pend && isdirsep(*unresolved_nextname))
|
|
|
|
unresolved_nextname++;
|
2010-01-12 03:32:22 +03:00
|
|
|
unresolved = unresolved_nextname;
|
|
|
|
if (testnamelen == 1 && testname[0] == '.') {
|
|
|
|
}
|
|
|
|
else if (testnamelen == 2 && testname[0] == '.' && testname[1] == '.') {
|
|
|
|
if (*prefixlenp < RSTRING_LEN(*resolvedp)) {
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *resolved_str = RSTRING_PTR(*resolvedp);
|
|
|
|
const char *resolved_names = resolved_str + *prefixlenp;
|
|
|
|
const char *lastsep = strrdirsep(resolved_names, resolved_str + RSTRING_LEN(*resolvedp), enc);
|
2010-02-03 14:08:44 +03:00
|
|
|
long len = lastsep ? lastsep - resolved_names : 0;
|
2010-08-06 13:59:31 +04:00
|
|
|
rb_str_resize(*resolvedp, *prefixlenp + len);
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
VALUE checkval;
|
|
|
|
VALUE testpath = rb_str_dup(*resolvedp);
|
|
|
|
if (*prefixlenp < RSTRING_LEN(testpath))
|
|
|
|
rb_str_cat2(testpath, "/");
|
2012-05-26 11:26:36 +04:00
|
|
|
#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
|
|
|
|
if (*prefixlenp > 1 && *prefixlenp == RSTRING_LEN(testpath)) {
|
|
|
|
const char *prefix = RSTRING_PTR(testpath);
|
|
|
|
const char *last = rb_enc_left_char_head(prefix, prefix + *prefixlenp - 1, prefix + *prefixlenp, enc);
|
|
|
|
if (!isdirsep(*last)) rb_str_cat2(testpath, "/");
|
|
|
|
}
|
|
|
|
#endif
|
2010-01-12 03:32:22 +03:00
|
|
|
rb_str_cat(testpath, testname, testnamelen);
|
|
|
|
checkval = rb_hash_aref(loopcheck, testpath);
|
|
|
|
if (!NIL_P(checkval)) {
|
2010-03-15 01:41:04 +03:00
|
|
|
if (checkval == ID2SYM(resolving)) {
|
2017-09-21 10:29:16 +03:00
|
|
|
if (mode == RB_REALPATH_CHECK) {
|
|
|
|
errno = ELOOP;
|
|
|
|
return -1;
|
|
|
|
}
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(ELOOP, testpath);
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
*resolvedp = rb_str_dup(checkval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
struct stat sbuf;
|
|
|
|
int ret;
|
2017-10-04 02:47:53 +03:00
|
|
|
ret = lstat_without_gvl(RSTRING_PTR(testpath), &sbuf);
|
2010-01-12 03:32:22 +03:00
|
|
|
if (ret == -1) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
2018-02-28 08:43:53 +03:00
|
|
|
if (e == ENOENT && !NIL_P(fallback)) {
|
|
|
|
if (stat_without_gvl(RSTRING_PTR(fallback), &sbuf) == 0) {
|
|
|
|
rb_str_replace(*resolvedp, fallback);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2017-09-21 10:29:16 +03:00
|
|
|
if (mode == RB_REALPATH_CHECK) return -1;
|
2015-12-23 11:57:48 +03:00
|
|
|
if (e == ENOENT) {
|
2017-09-21 10:29:16 +03:00
|
|
|
if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep)
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, testpath);
|
2010-01-12 03:32:22 +03:00
|
|
|
*resolvedp = testpath;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, testpath);
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
|
|
|
}
|
2010-01-12 07:35:53 +03:00
|
|
|
#ifdef HAVE_READLINK
|
2010-01-12 03:32:22 +03:00
|
|
|
if (S_ISLNK(sbuf.st_mode)) {
|
2012-01-25 06:32:06 +04:00
|
|
|
VALUE link;
|
2017-10-01 04:44:47 +03:00
|
|
|
VALUE link_orig = Qnil;
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *link_prefix, *link_names;
|
2010-01-12 03:32:22 +03:00
|
|
|
long link_prefixlen;
|
2010-03-15 01:41:04 +03:00
|
|
|
rb_hash_aset(loopcheck, testpath, ID2SYM(resolving));
|
2015-09-02 10:58:24 +03:00
|
|
|
link = rb_readlink(testpath, enc);
|
2010-01-12 03:32:22 +03:00
|
|
|
link_prefix = RSTRING_PTR(link);
|
2012-01-25 06:32:06 +04:00
|
|
|
link_names = skipprefixroot(link_prefix, link_prefix + RSTRING_LEN(link), rb_enc_get(link));
|
|
|
|
link_prefixlen = link_names - link_prefix;
|
|
|
|
if (link_prefixlen > 0) {
|
2017-10-18 07:35:25 +03:00
|
|
|
rb_encoding *tmpenc, *linkenc = rb_enc_get(link);
|
2012-10-12 22:01:56 +04:00
|
|
|
link_orig = link;
|
2012-01-25 06:32:06 +04:00
|
|
|
link = rb_str_subseq(link, 0, link_prefixlen);
|
2021-01-13 18:14:11 +03:00
|
|
|
tmpenc = fs_enc_check(*resolvedp, link);
|
2017-10-18 07:35:25 +03:00
|
|
|
if (tmpenc != linkenc) link = rb_str_conv_enc(link, linkenc, tmpenc);
|
2012-01-25 06:32:06 +04:00
|
|
|
*resolvedp = link;
|
|
|
|
*prefixlenp = link_prefixlen;
|
|
|
|
}
|
2018-02-28 08:43:53 +03:00
|
|
|
if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
|
2017-09-21 10:29:16 +03:00
|
|
|
loopcheck, mode, !*unresolved_firstsep))
|
|
|
|
return -1;
|
2012-10-12 22:01:56 +04:00
|
|
|
RB_GC_GUARD(link_orig);
|
2012-01-25 06:32:06 +04:00
|
|
|
rb_hash_aset(loopcheck, testpath, rb_str_dup_frozen(*resolvedp));
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
2010-01-12 07:35:53 +03:00
|
|
|
else
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* HAVE_READLINK */
|
2010-01-12 07:35:53 +03:00
|
|
|
{
|
2010-01-12 03:32:22 +03:00
|
|
|
VALUE s = rb_str_dup_frozen(testpath);
|
|
|
|
rb_hash_aset(loopcheck, s, s);
|
|
|
|
*resolvedp = testpath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-09-21 10:29:16 +03:00
|
|
|
return 0;
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
|
|
|
|
2017-09-21 10:29:16 +03:00
|
|
|
static VALUE
|
2019-12-03 02:12:57 +03:00
|
|
|
rb_check_realpath_emulate(VALUE basedir, VALUE path, rb_encoding *origenc, enum rb_realpath_mode mode)
|
2010-01-12 03:32:22 +03:00
|
|
|
{
|
|
|
|
long prefixlen;
|
|
|
|
VALUE resolved;
|
2017-10-01 04:44:47 +03:00
|
|
|
VALUE unresolved_path;
|
2010-01-12 03:32:22 +03:00
|
|
|
VALUE loopcheck;
|
2017-10-01 04:44:47 +03:00
|
|
|
VALUE curdir = Qnil;
|
2010-03-15 01:33:09 +03:00
|
|
|
|
2019-12-03 02:12:57 +03:00
|
|
|
rb_encoding *enc;
|
2010-03-07 07:55:34 +03:00
|
|
|
char *path_names = NULL, *basedir_names = NULL, *curdir_names = NULL;
|
2012-01-25 06:32:06 +04:00
|
|
|
char *ptr, *prefixptr = NULL, *pend;
|
|
|
|
long len;
|
2010-01-12 14:47:03 +03:00
|
|
|
|
2010-01-12 03:32:22 +03:00
|
|
|
unresolved_path = rb_str_dup_frozen(path);
|
2010-03-07 07:55:34 +03:00
|
|
|
|
|
|
|
if (!NIL_P(basedir)) {
|
|
|
|
FilePathValue(basedir);
|
2017-06-08 04:58:44 +03:00
|
|
|
basedir = TO_OSPATH(rb_str_dup_frozen(basedir));
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
2010-03-07 07:55:34 +03:00
|
|
|
|
2017-06-08 04:58:44 +03:00
|
|
|
enc = rb_enc_get(unresolved_path);
|
|
|
|
unresolved_path = TO_OSPATH(unresolved_path);
|
2012-01-25 06:32:06 +04:00
|
|
|
RSTRING_GETMEM(unresolved_path, ptr, len);
|
|
|
|
path_names = skipprefixroot(ptr, ptr + len, rb_enc_get(unresolved_path));
|
2010-03-07 07:55:34 +03:00
|
|
|
if (ptr != path_names) {
|
2012-01-25 06:32:06 +04:00
|
|
|
resolved = rb_str_subseq(unresolved_path, 0, path_names - ptr);
|
2010-03-07 07:55:34 +03:00
|
|
|
goto root_found;
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
2010-03-07 07:55:34 +03:00
|
|
|
|
|
|
|
if (!NIL_P(basedir)) {
|
2012-01-25 06:32:06 +04:00
|
|
|
RSTRING_GETMEM(basedir, ptr, len);
|
|
|
|
basedir_names = skipprefixroot(ptr, ptr + len, rb_enc_get(basedir));
|
2010-03-07 07:55:34 +03:00
|
|
|
if (ptr != basedir_names) {
|
2012-01-25 06:32:06 +04:00
|
|
|
resolved = rb_str_subseq(basedir, 0, basedir_names - ptr);
|
|
|
|
goto root_found;
|
2010-03-07 07:55:34 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-08 04:58:44 +03:00
|
|
|
curdir = rb_dir_getwd_ospath();
|
2012-01-25 06:32:06 +04:00
|
|
|
RSTRING_GETMEM(curdir, ptr, len);
|
|
|
|
curdir_names = skipprefixroot(ptr, ptr + len, rb_enc_get(curdir));
|
|
|
|
resolved = rb_str_subseq(curdir, 0, curdir_names - ptr);
|
2010-03-07 07:55:34 +03:00
|
|
|
|
|
|
|
root_found:
|
2012-01-25 06:32:06 +04:00
|
|
|
RSTRING_GETMEM(resolved, prefixptr, prefixlen);
|
|
|
|
pend = prefixptr + prefixlen;
|
|
|
|
ptr = chompdirsep(prefixptr, pend, enc);
|
|
|
|
if (ptr < pend) {
|
2010-03-15 01:33:09 +03:00
|
|
|
prefixlen = ++ptr - prefixptr;
|
|
|
|
rb_str_set_len(resolved, prefixlen);
|
2010-03-07 07:55:34 +03:00
|
|
|
}
|
2010-03-15 01:33:09 +03:00
|
|
|
#ifdef FILE_ALT_SEPARATOR
|
|
|
|
while (prefixptr < ptr) {
|
|
|
|
if (*prefixptr == FILE_ALT_SEPARATOR) {
|
|
|
|
*prefixptr = '/';
|
|
|
|
}
|
2012-01-25 06:32:06 +04:00
|
|
|
Inc(prefixptr, pend, enc);
|
2010-03-15 01:33:09 +03:00
|
|
|
}
|
|
|
|
#endif
|
2010-03-07 07:55:34 +03:00
|
|
|
|
2015-09-02 10:58:24 +03:00
|
|
|
switch (rb_enc_to_index(enc)) {
|
2022-07-13 12:54:08 +03:00
|
|
|
case ENCINDEX_ASCII_8BIT:
|
2015-09-02 10:58:24 +03:00
|
|
|
case ENCINDEX_US_ASCII:
|
2015-10-17 07:31:43 +03:00
|
|
|
rb_enc_associate_index(resolved, rb_filesystem_encindex());
|
2015-09-02 10:58:24 +03:00
|
|
|
}
|
|
|
|
|
2010-03-07 07:55:34 +03:00
|
|
|
loopcheck = rb_hash_new();
|
2017-09-21 10:29:16 +03:00
|
|
|
if (curdir_names) {
|
2018-02-28 08:43:53 +03:00
|
|
|
if (realpath_rec(&prefixlen, &resolved, curdir_names, Qnil, loopcheck, mode, 0))
|
2017-09-21 10:29:16 +03:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
if (basedir_names) {
|
2018-02-28 08:43:53 +03:00
|
|
|
if (realpath_rec(&prefixlen, &resolved, basedir_names, Qnil, loopcheck, mode, 0))
|
2017-09-21 10:29:16 +03:00
|
|
|
return Qnil;
|
|
|
|
}
|
2018-02-28 08:43:53 +03:00
|
|
|
if (realpath_rec(&prefixlen, &resolved, path_names, Qnil, loopcheck, mode, 1))
|
2017-09-21 10:29:16 +03:00
|
|
|
return Qnil;
|
2010-03-07 07:55:34 +03:00
|
|
|
|
2019-12-03 02:12:57 +03:00
|
|
|
if (origenc && origenc != rb_enc_get(resolved)) {
|
2017-06-08 04:58:44 +03:00
|
|
|
if (rb_enc_str_asciionly_p(resolved)) {
|
|
|
|
rb_enc_associate(resolved, origenc);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
resolved = rb_str_conv_enc(resolved, NULL, origenc);
|
|
|
|
}
|
|
|
|
}
|
2015-09-02 10:58:24 +03:00
|
|
|
|
2017-10-01 04:44:47 +03:00
|
|
|
RB_GC_GUARD(unresolved_path);
|
|
|
|
RB_GC_GUARD(curdir);
|
2010-01-12 03:32:22 +03:00
|
|
|
return resolved;
|
|
|
|
}
|
2017-09-21 10:29:16 +03:00
|
|
|
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
static VALUE rb_file_join(VALUE ary);
|
|
|
|
|
2021-10-05 00:13:47 +03:00
|
|
|
#ifndef HAVE_REALPATH
|
|
|
|
static VALUE
|
|
|
|
rb_check_realpath_emulate_try(VALUE arg)
|
|
|
|
{
|
|
|
|
VALUE *args = (VALUE *)arg;
|
2021-10-14 04:22:55 +03:00
|
|
|
return rb_check_realpath_emulate(args[0], args[1], (rb_encoding *)args[2], RB_REALPATH_CHECK);
|
2021-10-05 00:13:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_check_realpath_emulate_rescue(VALUE arg, VALUE exc)
|
|
|
|
{
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_REALPATH */
|
|
|
|
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
static VALUE
|
2019-12-03 02:12:57 +03:00
|
|
|
rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum rb_realpath_mode mode)
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
{
|
|
|
|
#ifdef HAVE_REALPATH
|
|
|
|
VALUE unresolved_path;
|
|
|
|
char *resolved_ptr = NULL;
|
|
|
|
VALUE resolved;
|
|
|
|
|
|
|
|
if (mode == RB_REALPATH_DIR) {
|
2019-12-03 02:12:57 +03:00
|
|
|
return rb_check_realpath_emulate(basedir, path, origenc, mode);
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
unresolved_path = rb_str_dup_frozen(path);
|
|
|
|
if (*RSTRING_PTR(unresolved_path) != '/' && !NIL_P(basedir)) {
|
2019-07-01 22:14:17 +03:00
|
|
|
unresolved_path = rb_file_join(rb_assoc_new(basedir, unresolved_path));
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
}
|
2019-12-03 02:12:57 +03:00
|
|
|
if (origenc) unresolved_path = TO_OSPATH(unresolved_path);
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
|
2019-09-27 04:20:56 +03:00
|
|
|
if ((resolved_ptr = realpath(RSTRING_PTR(unresolved_path), NULL)) == NULL) {
|
2019-07-01 22:14:17 +03:00
|
|
|
/* glibc realpath(3) does not allow /path/to/file.rb/../other_file.rb,
|
|
|
|
returning ENOTDIR in that case.
|
|
|
|
glibc realpath(3) can also return ENOENT for paths that exist,
|
|
|
|
such as /dev/fd/5.
|
|
|
|
Fallback to the emulated approach in either of those cases. */
|
|
|
|
if (errno == ENOTDIR ||
|
|
|
|
(errno == ENOENT && rb_file_exist_p(0, unresolved_path))) {
|
2019-12-03 02:12:57 +03:00
|
|
|
return rb_check_realpath_emulate(basedir, path, origenc, mode);
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
|
2019-07-01 22:14:17 +03:00
|
|
|
}
|
|
|
|
if (mode == RB_REALPATH_CHECK) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
rb_sys_fail_path(unresolved_path);
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
}
|
|
|
|
resolved = ospath_new(resolved_ptr, strlen(resolved_ptr), rb_filesystem_encoding());
|
|
|
|
free(resolved_ptr);
|
|
|
|
|
2020-06-28 00:10:42 +03:00
|
|
|
# if !defined(__LINUX__) && !defined(__APPLE__)
|
2019-12-03 02:12:57 +03:00
|
|
|
/* As `resolved` is a String in the filesystem encoding, no
|
|
|
|
* conversion is needed */
|
2020-06-28 00:10:42 +03:00
|
|
|
struct stat st;
|
2019-12-03 02:12:57 +03:00
|
|
|
if (stat_without_gvl(RSTRING_PTR(resolved), &st) < 0) {
|
2019-07-01 22:14:17 +03:00
|
|
|
if (mode == RB_REALPATH_CHECK) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
rb_sys_fail_path(unresolved_path);
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
# endif /* !defined(__LINUX__) && !defined(__APPLE__) */
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
|
2019-12-03 02:12:57 +03:00
|
|
|
if (origenc && origenc != rb_enc_get(resolved)) {
|
2019-07-01 22:14:17 +03:00
|
|
|
if (!rb_enc_str_asciionly_p(resolved)) {
|
|
|
|
resolved = rb_str_conv_enc(resolved, NULL, origenc);
|
|
|
|
}
|
|
|
|
rb_enc_associate(resolved, origenc);
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
}
|
|
|
|
|
2022-09-09 20:00:34 +03:00
|
|
|
if (is_broken_string(resolved)) {
|
2019-07-01 22:14:17 +03:00
|
|
|
rb_enc_associate(resolved, rb_filesystem_encoding());
|
2022-09-09 20:00:34 +03:00
|
|
|
if (is_broken_string(resolved)) {
|
2019-07-01 22:14:17 +03:00
|
|
|
rb_enc_associate(resolved, rb_ascii8bit_encoding());
|
|
|
|
}
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
RB_GC_GUARD(unresolved_path);
|
|
|
|
return resolved;
|
2023-01-31 01:50:37 +03:00
|
|
|
#else /* !HAVE_REALPATH */
|
2021-10-05 00:13:47 +03:00
|
|
|
if (mode == RB_REALPATH_CHECK) {
|
|
|
|
VALUE arg[3];
|
|
|
|
arg[0] = basedir;
|
|
|
|
arg[1] = path;
|
|
|
|
arg[2] = (VALUE)origenc;
|
|
|
|
|
|
|
|
return rb_rescue(rb_check_realpath_emulate_try, (VALUE)arg,
|
|
|
|
rb_check_realpath_emulate_rescue, Qnil);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return rb_check_realpath_emulate(basedir, path, origenc, mode);
|
|
|
|
}
|
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to
emulate realpath(3). It also performs much better on both Linux and
OpenBSD on the included benchmarks.
By using realpath(3), we can better integrate with system security
features such as OpenBSD's unveil(2) system call.
This does not use realpath(3) on Windows even if it exists, as the
approach for checking for absolute paths does not work for drive
letters. This can be fixed without too much difficultly, though until
Windows defines realpath(3), there is no need to do so.
For File.realdirpath, where the last element of the path is not
required to exist, fallback to the previous approach, as realpath(3)
on most operating systems requires the whole path be valid (per POSIX),
and the operating systems where this isn't true either plan to conform
to POSIX or may change to conform to POSIX in the future.
glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb
paths, returning ENOTDIR in that case. Fallback to the previous code
if realpath(3) returns ENOTDIR.
glibc doesn't like realpath(3) usage for paths like /dev/fd/5,
returning ENOENT even though the path may appear to exist in the
filesystem. If ENOENT is returned and the path exists, then fall
back to the default approach.
2019-04-28 06:18:55 +03:00
|
|
|
#endif /* HAVE_REALPATH */
|
|
|
|
}
|
|
|
|
|
2017-09-21 10:29:16 +03:00
|
|
|
VALUE
|
|
|
|
rb_realpath_internal(VALUE basedir, VALUE path, int strict)
|
|
|
|
{
|
|
|
|
const enum rb_realpath_mode mode =
|
|
|
|
strict ? RB_REALPATH_STRICT : RB_REALPATH_DIR;
|
2019-12-03 02:12:57 +03:00
|
|
|
return rb_check_realpath_internal(basedir, path, rb_enc_get(path), mode);
|
2017-09-21 10:29:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
2019-12-03 02:12:57 +03:00
|
|
|
rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *enc)
|
2017-09-21 10:29:16 +03:00
|
|
|
{
|
2019-12-03 02:12:57 +03:00
|
|
|
return rb_check_realpath_internal(basedir, path, enc, RB_REALPATH_CHECK);
|
2017-09-21 10:29:16 +03:00
|
|
|
}
|
2010-01-12 03:32:22 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.realpath(pathname [, dir_string]) -> real_pathname
|
2010-01-12 03:32:22 +03:00
|
|
|
*
|
2010-03-07 07:55:34 +03:00
|
|
|
* Returns the real (absolute) pathname of _pathname_ in the actual
|
2010-01-12 03:32:22 +03:00
|
|
|
* filesystem not containing symlinks or useless dots.
|
2010-03-07 07:55:34 +03:00
|
|
|
*
|
|
|
|
* If _dir_string_ is given, it is used as a base directory
|
|
|
|
* for interpreting relative pathname instead of the current directory.
|
2010-05-29 22:51:39 +04:00
|
|
|
*
|
2010-01-12 03:32:22 +03:00
|
|
|
* All components of the pathname must exist when this method is
|
|
|
|
* called.
|
|
|
|
*/
|
|
|
|
static VALUE
|
2010-03-07 07:55:34 +03:00
|
|
|
rb_file_s_realpath(int argc, VALUE *argv, VALUE klass)
|
2010-01-12 03:32:22 +03:00
|
|
|
{
|
2016-04-11 00:59:02 +03:00
|
|
|
VALUE basedir = (rb_check_arity(argc, 1, 2) > 1) ? argv[1] : Qnil;
|
|
|
|
VALUE path = argv[0];
|
2016-04-10 11:47:44 +03:00
|
|
|
FilePathValue(path);
|
2010-03-16 20:40:00 +03:00
|
|
|
return rb_realpath_internal(basedir, path, 1);
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.realdirpath(pathname [, dir_string]) -> real_pathname
|
2010-01-12 03:32:22 +03:00
|
|
|
*
|
2010-03-07 07:55:34 +03:00
|
|
|
* Returns the real (absolute) pathname of _pathname_ in the actual filesystem.
|
2010-01-12 03:32:22 +03:00
|
|
|
* The real pathname doesn't contain symlinks or useless dots.
|
2010-05-29 22:51:39 +04:00
|
|
|
*
|
2010-03-07 07:55:34 +03:00
|
|
|
* If _dir_string_ is given, it is used as a base directory
|
|
|
|
* for interpreting relative pathname instead of the current directory.
|
2010-05-29 22:51:39 +04:00
|
|
|
*
|
2010-01-12 03:32:22 +03:00
|
|
|
* The last component of the real pathname can be nonexistent.
|
|
|
|
*/
|
|
|
|
static VALUE
|
2010-03-07 07:55:34 +03:00
|
|
|
rb_file_s_realdirpath(int argc, VALUE *argv, VALUE klass)
|
2010-01-12 03:32:22 +03:00
|
|
|
{
|
2016-04-11 00:59:02 +03:00
|
|
|
VALUE basedir = (rb_check_arity(argc, 1, 2) > 1) ? argv[1] : Qnil;
|
|
|
|
VALUE path = argv[0];
|
2016-04-10 11:47:44 +03:00
|
|
|
FilePathValue(path);
|
2010-03-16 20:40:00 +03:00
|
|
|
return rb_realpath_internal(basedir, path, 0);
|
2010-01-12 03:32:22 +03:00
|
|
|
}
|
|
|
|
|
2009-04-06 11:38:52 +04:00
|
|
|
static size_t
|
2014-06-03 00:23:47 +04:00
|
|
|
rmext(const char *p, long l0, long l1, const char *e, long l2, rb_encoding *enc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
int len1, len2;
|
|
|
|
unsigned int c;
|
|
|
|
const char *s, *last;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2012-01-25 06:40:29 +04:00
|
|
|
if (!e || !l2) return 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2012-01-25 06:32:06 +04:00
|
|
|
c = rb_enc_codepoint_len(e, e + l2, &len1, enc);
|
|
|
|
if (rb_enc_ascget(e + len1, e + l2, &len2, enc) == '*' && len1 + len2 == l2) {
|
|
|
|
if (c == '.') return l0;
|
|
|
|
s = p;
|
2008-05-15 10:34:02 +04:00
|
|
|
e = p + l1;
|
2012-01-25 06:32:06 +04:00
|
|
|
last = e;
|
|
|
|
while (s < e) {
|
|
|
|
if (rb_enc_codepoint_len(s, e, &len1, enc) == c) last = s;
|
|
|
|
s += len1;
|
|
|
|
}
|
|
|
|
return last - p;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
if (l1 < l2) return l1;
|
|
|
|
|
2012-01-25 06:32:06 +04:00
|
|
|
s = p+l1-l2;
|
2023-08-24 12:32:46 +03:00
|
|
|
if (!at_char_boundary(p, s, p+l1, enc)) return 0;
|
2008-05-15 10:34:02 +04:00
|
|
|
#if CASEFOLD_FILESYSTEM
|
|
|
|
#define fncomp strncasecmp
|
|
|
|
#else
|
|
|
|
#define fncomp strncmp
|
|
|
|
#endif
|
2012-01-25 06:32:06 +04:00
|
|
|
if (fncomp(s, e, l2) == 0) {
|
1998-01-16 15:13:05 +03:00
|
|
|
return l1-l2;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-07-02 18:31:26 +04:00
|
|
|
const char *
|
2014-06-03 00:23:47 +04:00
|
|
|
ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *p, *q, *e, *end;
|
2005-11-21 19:47:13 +03:00
|
|
|
#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
|
2008-06-01 23:55:25 +04:00
|
|
|
const char *root;
|
2005-11-21 16:21:47 +03:00
|
|
|
#endif
|
2010-07-07 07:03:19 +04:00
|
|
|
long f = 0, n = -1;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2012-03-15 10:03:02 +04:00
|
|
|
end = name + (alllen ? (size_t)*alllen : strlen(name));
|
2012-01-25 06:32:06 +04:00
|
|
|
name = skipprefix(name, end, enc);
|
2005-11-21 19:47:13 +03:00
|
|
|
#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
|
2005-11-21 16:21:47 +03:00
|
|
|
root = name;
|
|
|
|
#endif
|
|
|
|
while (isdirsep(*name))
|
|
|
|
name++;
|
|
|
|
if (!*name) {
|
2003-02-12 17:56:45 +03:00
|
|
|
p = name - 1;
|
|
|
|
f = 1;
|
2005-11-21 19:47:13 +03:00
|
|
|
#if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
|
2005-11-21 16:21:47 +03:00
|
|
|
if (name != root) {
|
|
|
|
/* has slashes */
|
|
|
|
}
|
2003-02-12 17:56:45 +03:00
|
|
|
#ifdef DOSISH_DRIVE_LETTER
|
2005-11-21 16:21:47 +03:00
|
|
|
else if (*p == ':') {
|
2003-02-12 17:56:45 +03:00
|
|
|
p++;
|
|
|
|
f = 0;
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* DOSISH_DRIVE_LETTER */
|
2005-11-21 16:21:47 +03:00
|
|
|
#ifdef DOSISH_UNC
|
|
|
|
else {
|
|
|
|
p = "/";
|
|
|
|
}
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* DOSISH_UNC */
|
|
|
|
#endif /* defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC */
|
2003-02-12 17:56:45 +03:00
|
|
|
}
|
2000-05-30 08:24:17 +04:00
|
|
|
else {
|
2012-01-25 06:32:06 +04:00
|
|
|
if (!(p = strrdirsep(name, end, enc))) {
|
2008-05-15 10:34:02 +04:00
|
|
|
p = name;
|
2000-05-30 08:24:17 +04:00
|
|
|
}
|
2008-05-15 10:34:02 +04:00
|
|
|
else {
|
|
|
|
while (isdirsep(*p)) p++; /* skip last / */
|
|
|
|
}
|
|
|
|
#if USE_NTFS
|
2012-01-25 06:32:06 +04:00
|
|
|
n = ntfs_tail(p, end, enc) - p;
|
2008-05-15 10:34:02 +04:00
|
|
|
#else
|
2012-01-25 06:32:06 +04:00
|
|
|
n = chompdirsep(p, end, enc) - p;
|
2008-05-15 10:34:02 +04:00
|
|
|
#endif
|
2010-07-07 08:22:30 +04:00
|
|
|
for (q = p; q - p < n && *q == '.'; q++);
|
2012-01-25 06:32:06 +04:00
|
|
|
for (e = 0; q - p < n; Inc(q, end, enc)) {
|
2010-07-07 08:22:30 +04:00
|
|
|
if (*q == '.') e = q;
|
|
|
|
}
|
|
|
|
if (e) f = e - p;
|
|
|
|
else f = n;
|
2010-07-02 18:31:26 +04:00
|
|
|
}
|
|
|
|
|
2010-07-07 08:22:30 +04:00
|
|
|
if (baselen)
|
|
|
|
*baselen = f;
|
|
|
|
if (alllen)
|
|
|
|
*alllen = n;
|
2010-07-02 18:31:26 +04:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* File.basename(file_name [, suffix] ) -> base_name
|
|
|
|
*
|
2017-09-16 14:50:56 +03:00
|
|
|
* Returns the last component of the filename given in
|
|
|
|
* <i>file_name</i> (after first stripping trailing separators),
|
2019-03-22 14:04:59 +03:00
|
|
|
* which can be formed using both File::SEPARATOR and
|
|
|
|
* File::ALT_SEPARATOR as the separator when File::ALT_SEPARATOR is
|
|
|
|
* not <code>nil</code>. If <i>suffix</i> is given and present at the
|
|
|
|
* end of <i>file_name</i>, it is removed. If <i>suffix</i> is ".*",
|
|
|
|
* any extension will be removed.
|
2010-07-02 18:31:26 +04:00
|
|
|
*
|
|
|
|
* File.basename("/home/gumby/work/ruby.rb") #=> "ruby.rb"
|
|
|
|
* File.basename("/home/gumby/work/ruby.rb", ".rb") #=> "ruby"
|
2014-02-28 04:37:16 +04:00
|
|
|
* File.basename("/home/gumby/work/ruby.rb", ".*") #=> "ruby"
|
2010-07-02 18:31:26 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_basename(int argc, VALUE *argv, VALUE _)
|
2010-07-02 18:31:26 +04:00
|
|
|
{
|
|
|
|
VALUE fname, fext, basename;
|
|
|
|
const char *name, *p;
|
|
|
|
long f, n;
|
2012-01-25 06:32:06 +04:00
|
|
|
rb_encoding *enc;
|
2010-07-02 18:31:26 +04:00
|
|
|
|
2016-04-11 00:59:02 +03:00
|
|
|
fext = Qnil;
|
|
|
|
if (rb_check_arity(argc, 1, 2) == 2) {
|
|
|
|
fext = argv[1];
|
2010-07-02 18:31:26 +04:00
|
|
|
StringValue(fext);
|
2012-10-16 05:53:32 +04:00
|
|
|
enc = check_path_encoding(fext);
|
2010-07-02 18:31:26 +04:00
|
|
|
}
|
2016-04-11 00:59:02 +03:00
|
|
|
fname = argv[0];
|
2010-07-02 18:31:26 +04:00
|
|
|
FilePathStringValue(fname);
|
2012-01-25 08:27:45 +04:00
|
|
|
if (NIL_P(fext) || !(enc = rb_enc_compatible(fname, fext))) {
|
|
|
|
enc = rb_enc_get(fname);
|
|
|
|
fext = Qnil;
|
|
|
|
}
|
2012-01-25 06:32:06 +04:00
|
|
|
if ((n = RSTRING_LEN(fname)) == 0 || !*(name = RSTRING_PTR(fname)))
|
2010-07-02 18:31:26 +04:00
|
|
|
return rb_str_new_shared(fname);
|
|
|
|
|
2012-01-25 06:32:06 +04:00
|
|
|
p = ruby_enc_find_basename(name, &f, &n, enc);
|
2010-07-02 18:31:26 +04:00
|
|
|
if (n >= 0) {
|
2012-01-25 06:32:06 +04:00
|
|
|
if (NIL_P(fext)) {
|
2008-05-15 10:34:02 +04:00
|
|
|
f = n;
|
|
|
|
}
|
2012-01-25 06:32:06 +04:00
|
|
|
else {
|
|
|
|
const char *fp;
|
|
|
|
fp = StringValueCStr(fext);
|
|
|
|
if (!(f = rmext(p, f, n, fp, RSTRING_LEN(fext), enc))) {
|
|
|
|
f = n;
|
|
|
|
}
|
|
|
|
RB_GC_GUARD(fext);
|
|
|
|
}
|
2009-07-08 11:47:09 +04:00
|
|
|
if (f == RSTRING_LEN(fname)) return rb_str_new_shared(fname);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2010-07-02 18:31:26 +04:00
|
|
|
|
2003-02-12 17:56:45 +03:00
|
|
|
basename = rb_str_new(p, f);
|
2008-04-11 22:12:18 +04:00
|
|
|
rb_enc_copy(basename, fname);
|
1999-12-01 12:24:48 +03:00
|
|
|
return basename;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2016-03-18 10:40:45 +03:00
|
|
|
static VALUE rb_file_dirname_n(VALUE fname, int n);
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-03-18 10:40:45 +03:00
|
|
|
* File.dirname(file_name, level = 1) -> dir_name
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns all components of the filename given in <i>file_name</i>
|
2017-09-16 14:50:56 +03:00
|
|
|
* except the last one (after first stripping trailing separators).
|
2019-03-22 14:04:59 +03:00
|
|
|
* The filename can be formed using both File::SEPARATOR and
|
|
|
|
* File::ALT_SEPARATOR as the separator when File::ALT_SEPARATOR is
|
|
|
|
* not <code>nil</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work"
|
2016-03-18 10:40:45 +03:00
|
|
|
*
|
|
|
|
* If +level+ is given, removes the last +level+ components, not only
|
|
|
|
* one.
|
|
|
|
*
|
|
|
|
* File.dirname("/home/gumby/work/ruby.rb", 2) #=> "/home/gumby"
|
|
|
|
* File.dirname("/home/gumby/work/ruby.rb", 4) #=> "/"
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2010-03-30 13:26:09 +04:00
|
|
|
static VALUE
|
2016-03-18 10:40:45 +03:00
|
|
|
rb_file_s_dirname(int argc, VALUE *argv, VALUE klass)
|
2010-03-30 13:26:09 +04:00
|
|
|
{
|
2016-03-18 10:40:45 +03:00
|
|
|
int n = 1;
|
|
|
|
if ((argc = rb_check_arity(argc, 1, 2)) > 1) {
|
|
|
|
n = NUM2INT(argv[1]);
|
|
|
|
}
|
|
|
|
return rb_file_dirname_n(argv[0], n);
|
2010-03-30 13:26:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_file_dirname(VALUE fname)
|
2016-03-18 10:40:45 +03:00
|
|
|
{
|
|
|
|
return rb_file_dirname_n(fname, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_file_dirname_n(VALUE fname, int n)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *name, *root, *p, *end;
|
1999-12-01 12:24:48 +03:00
|
|
|
VALUE dirname;
|
2012-01-25 06:32:06 +04:00
|
|
|
rb_encoding *enc;
|
2016-03-18 10:40:45 +03:00
|
|
|
VALUE sepsv = 0;
|
|
|
|
const char **seps;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2016-03-18 10:40:45 +03:00
|
|
|
if (n < 0) rb_raise(rb_eArgError, "negative level: %d", n);
|
2007-12-09 08:12:31 +03:00
|
|
|
FilePathStringValue(fname);
|
2003-07-20 21:17:52 +04:00
|
|
|
name = StringValueCStr(fname);
|
2012-01-25 06:32:06 +04:00
|
|
|
end = name + RSTRING_LEN(fname);
|
|
|
|
enc = rb_enc_get(fname);
|
|
|
|
root = skiproot(name, end, enc);
|
2003-02-12 17:56:45 +03:00
|
|
|
#ifdef DOSISH_UNC
|
2005-11-18 12:09:25 +03:00
|
|
|
if (root > name + 1 && isdirsep(*name))
|
2012-01-25 06:32:06 +04:00
|
|
|
root = skipprefix(name = root - 2, end, enc);
|
2003-02-12 17:56:45 +03:00
|
|
|
#else
|
|
|
|
if (root > name + 1)
|
|
|
|
name = root - 1;
|
2003-01-06 12:44:15 +03:00
|
|
|
#endif
|
2016-03-18 10:40:45 +03:00
|
|
|
if (n > (end - root + 1) / 2) {
|
2003-02-12 17:56:45 +03:00
|
|
|
p = root;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2016-03-18 10:40:45 +03:00
|
|
|
else {
|
|
|
|
int i;
|
|
|
|
switch (n) {
|
|
|
|
case 0:
|
|
|
|
p = end;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (!(p = strrdirsep(root, end, enc))) p = root;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
seps = ALLOCV_N(const char *, sepsv, n);
|
2021-04-02 03:55:15 +03:00
|
|
|
for (i = 0; i < n; ++i) seps[i] = root;
|
2016-03-18 10:40:45 +03:00
|
|
|
i = 0;
|
|
|
|
for (p = root; p < end; ) {
|
|
|
|
if (isdirsep(*p)) {
|
|
|
|
const char *tmp = p++;
|
|
|
|
while (p < end && isdirsep(*p)) p++;
|
|
|
|
if (p >= end) break;
|
|
|
|
seps[i++] = tmp;
|
|
|
|
if (i == n) i = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Inc(p, end, enc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p = seps[i];
|
|
|
|
ALLOCV_END(sepsv);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
if (p == name)
|
* string.c (rb_str_usascii_new{,2}: defined.
(rb_str_new): set US-ASCII and ENC_CODERANGE_7BIT when empty
string.
* encoding.c (rb_usascii_encoding, rb_usascii_encindex): defined.
(rb_enc_inspect, enc_name, rb_locale_charmap, rb_enc_name_list_i):
use rb_str_ascii_new.
* array.c (recursive_join, inspect_ary): ditto.
* object.c (nil_to_s, nil_inspect, true_to_s, false_to_s,
rb_mod_to_s): ditto.
* hash.c (inspect_hash, rb_hash_inspect, rb_f_getenv, env_fetch,
env_clear, env_to_s, env_inspect): ditto.
* numeric.c (flo_to_s, int_chr, rb_fix2str): ditto.
* bignum.c (rb_big2str): ditto.
* file.c (rb_file_ftype, rb_file_s_dirname, rb_file_s_extname,
file_inspect_join, Init_file): ditto.
* test/ruby/test_ruby_m17n.rb: add checks for encoding of string.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15244 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-01-25 19:40:02 +03:00
|
|
|
return rb_usascii_str_new2(".");
|
2005-11-18 10:51:19 +03:00
|
|
|
#ifdef DOSISH_DRIVE_LETTER
|
|
|
|
if (has_drive_letter(name) && isdirsep(*(name + 2))) {
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *top = skiproot(name + 2, end, enc);
|
2005-11-18 10:51:19 +03:00
|
|
|
dirname = rb_str_new(name, 3);
|
2006-09-25 16:25:29 +04:00
|
|
|
rb_str_cat(dirname, top, p - top);
|
2005-11-18 10:51:19 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
1999-12-01 12:24:48 +03:00
|
|
|
dirname = rb_str_new(name, p - name);
|
2003-02-12 18:10:51 +03:00
|
|
|
#ifdef DOSISH_DRIVE_LETTER
|
2005-11-18 10:51:19 +03:00
|
|
|
if (has_drive_letter(name) && root == name + 2 && p - name == 2)
|
2003-02-12 18:10:51 +03:00
|
|
|
rb_str_cat(dirname, ".", 1);
|
|
|
|
#endif
|
2008-04-11 22:12:18 +04:00
|
|
|
rb_enc_copy(dirname, fname);
|
1999-12-01 12:24:48 +03:00
|
|
|
return dirname;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
2010-07-02 18:31:26 +04:00
|
|
|
* accept a String, and return the pointer of the extension.
|
|
|
|
* if len is passed, set the length of extension to it.
|
|
|
|
* returned pointer is in ``name'' or NULL.
|
|
|
|
* returns *len
|
|
|
|
* no dot NULL 0
|
|
|
|
* dotfile top 0
|
|
|
|
* end with dot dot 1
|
|
|
|
* .ext dot len of .ext
|
2022-10-05 13:35:36 +03:00
|
|
|
* .ext:stream dot len of .ext without :stream (NTFS only)
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
2010-07-02 18:31:26 +04:00
|
|
|
const char *
|
2014-06-03 00:23:47 +04:00
|
|
|
ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc)
|
2002-04-10 12:45:26 +04:00
|
|
|
{
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *p, *e, *end = name + (len ? *len : (long)strlen(name));
|
2002-04-10 12:45:26 +04:00
|
|
|
|
2012-01-25 06:32:06 +04:00
|
|
|
p = strrdirsep(name, end, enc); /* get the last path component */
|
2002-04-10 12:45:26 +04:00
|
|
|
if (!p)
|
2008-05-15 10:34:02 +04:00
|
|
|
p = name;
|
2002-04-10 12:45:26 +04:00
|
|
|
else
|
2010-04-19 19:43:05 +04:00
|
|
|
do name = ++p; while (isdirsep(*p));
|
2008-05-15 10:34:02 +04:00
|
|
|
|
|
|
|
e = 0;
|
2008-09-26 23:28:44 +04:00
|
|
|
while (*p && *p == '.') p++;
|
2008-05-15 10:34:02 +04:00
|
|
|
while (*p) {
|
2009-05-31 18:26:40 +04:00
|
|
|
if (*p == '.' || istrailinggarbage(*p)) {
|
2008-05-15 10:34:02 +04:00
|
|
|
#if USE_NTFS
|
2019-12-23 05:54:25 +03:00
|
|
|
const char *last = p++, *dot = last;
|
2009-05-31 18:26:40 +04:00
|
|
|
while (istrailinggarbage(*p)) {
|
2019-12-23 05:54:25 +03:00
|
|
|
if (*p == '.') dot = p;
|
2008-05-15 10:34:02 +04:00
|
|
|
p++;
|
|
|
|
}
|
2016-12-06 10:21:55 +03:00
|
|
|
if (!*p || isADS(*p)) {
|
2019-12-23 05:54:25 +03:00
|
|
|
p = last;
|
2008-05-15 10:34:02 +04:00
|
|
|
break;
|
|
|
|
}
|
2009-02-18 06:35:34 +03:00
|
|
|
if (*last == '.' || dot > last) e = dot;
|
2008-05-15 10:34:02 +04:00
|
|
|
continue;
|
|
|
|
#else
|
|
|
|
e = p; /* get the last dot of the last component */
|
2023-01-31 01:50:37 +03:00
|
|
|
#endif /* USE_NTFS */
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
|
|
|
#if USE_NTFS
|
2016-12-06 10:21:55 +03:00
|
|
|
else if (isADS(*p)) {
|
2008-05-15 10:34:02 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else if (isdirsep(*p))
|
|
|
|
break;
|
2012-01-25 06:32:06 +04:00
|
|
|
Inc(p, end, enc);
|
2008-05-15 10:34:02 +04:00
|
|
|
}
|
2010-07-02 18:31:26 +04:00
|
|
|
|
|
|
|
if (len) {
|
|
|
|
/* no dot, or the only dot is first or end? */
|
|
|
|
if (!e || e == name)
|
|
|
|
*len = 0;
|
|
|
|
else if (e+1 == p)
|
|
|
|
*len = 1;
|
|
|
|
else
|
|
|
|
*len = p - e;
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* File.extname(path) -> string
|
|
|
|
*
|
2012-11-20 10:37:53 +04:00
|
|
|
* Returns the extension (the portion of file name in +path+
|
|
|
|
* starting from the last period).
|
|
|
|
*
|
2012-11-20 16:34:45 +04:00
|
|
|
* If +path+ is a dotfile, or starts with a period, then the starting
|
|
|
|
* dot is not dealt with the start of the extension.
|
2012-11-20 10:37:53 +04:00
|
|
|
*
|
|
|
|
* An empty string will also be returned when the period is the last character
|
|
|
|
* in +path+.
|
2010-07-02 18:31:26 +04:00
|
|
|
*
|
2019-10-17 13:42:25 +03:00
|
|
|
* On Windows, trailing dots are truncated.
|
|
|
|
*
|
2010-07-02 18:31:26 +04:00
|
|
|
* File.extname("test.rb") #=> ".rb"
|
|
|
|
* File.extname("a/b/d/test.rb") #=> ".rb"
|
2015-07-24 10:35:38 +03:00
|
|
|
* File.extname(".a/b/d/test.rb") #=> ".rb"
|
2019-12-23 05:54:25 +03:00
|
|
|
* File.extname("foo.") #=> "" on Windows
|
|
|
|
* File.extname("foo.") #=> "." on non-Windows
|
2010-07-02 18:31:26 +04:00
|
|
|
* File.extname("test") #=> ""
|
|
|
|
* File.extname(".profile") #=> ""
|
2012-11-20 16:34:45 +04:00
|
|
|
* File.extname(".profile.sh") #=> ".sh"
|
2010-07-02 18:31:26 +04:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
rb_file_s_extname(VALUE klass, VALUE fname)
|
|
|
|
{
|
|
|
|
const char *name, *e;
|
|
|
|
long len;
|
|
|
|
VALUE extname;
|
|
|
|
|
|
|
|
FilePathStringValue(fname);
|
|
|
|
name = StringValueCStr(fname);
|
2012-01-25 06:32:06 +04:00
|
|
|
len = RSTRING_LEN(fname);
|
|
|
|
e = ruby_enc_find_extname(name, &len, rb_enc_get(fname));
|
2019-10-17 08:42:38 +03:00
|
|
|
if (len < 1)
|
* string.c (rb_str_usascii_new{,2}: defined.
(rb_str_new): set US-ASCII and ENC_CODERANGE_7BIT when empty
string.
* encoding.c (rb_usascii_encoding, rb_usascii_encindex): defined.
(rb_enc_inspect, enc_name, rb_locale_charmap, rb_enc_name_list_i):
use rb_str_ascii_new.
* array.c (recursive_join, inspect_ary): ditto.
* object.c (nil_to_s, nil_inspect, true_to_s, false_to_s,
rb_mod_to_s): ditto.
* hash.c (inspect_hash, rb_hash_inspect, rb_f_getenv, env_fetch,
env_clear, env_to_s, env_inspect): ditto.
* numeric.c (flo_to_s, int_chr, rb_fix2str): ditto.
* bignum.c (rb_big2str): ditto.
* file.c (rb_file_ftype, rb_file_s_dirname, rb_file_s_extname,
file_inspect_join, Init_file): ditto.
* test/ruby/test_ruby_m17n.rb: add checks for encoding of string.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15244 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-01-25 19:40:02 +03:00
|
|
|
return rb_str_new(0, 0);
|
2012-01-25 06:32:06 +04:00
|
|
|
extname = rb_str_subseq(fname, e - name, len); /* keep the dot, too! */
|
2005-09-20 17:25:59 +04:00
|
|
|
return extname;
|
2002-04-10 12:45:26 +04:00
|
|
|
}
|
|
|
|
|
2004-04-07 06:51:05 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.path(path) -> string
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2004-04-07 06:51:05 +04:00
|
|
|
* Returns the string representation of the path
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2023-07-10 13:18:48 +03:00
|
|
|
* File.path(File::NULL) #=> "/dev/null"
|
2004-04-07 06:51:05 +04:00
|
|
|
* File.path(Pathname.new("/tmp")) #=> "/tmp"
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2004-04-07 06:51:05 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_path(VALUE klass, VALUE fname)
|
2004-04-07 06:51:05 +04:00
|
|
|
{
|
|
|
|
return rb_get_path(fname);
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.split(file_name) -> array
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Splits the given string into a directory and a file component and
|
2019-03-22 14:04:59 +03:00
|
|
|
* returns them in a two-element array. See also File::dirname and
|
|
|
|
* File::basename.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.split("/home/gumby/.profile") #=> ["/home/gumby", ".profile"]
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_split(VALUE klass, VALUE path)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2007-12-09 08:12:31 +03:00
|
|
|
FilePathStringValue(path); /* get rid of converting twice */
|
2019-08-29 05:47:20 +03:00
|
|
|
return rb_assoc_new(rb_file_dirname(path), rb_file_s_basename(1,&path,Qundef));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-01-06 12:44:15 +03:00
|
|
|
static VALUE
|
2017-03-13 12:29:19 +03:00
|
|
|
file_inspect_join(VALUE ary, VALUE arg, int recur)
|
2003-01-06 12:44:15 +03:00
|
|
|
{
|
2017-03-13 12:29:19 +03:00
|
|
|
if (recur || ary == arg) rb_raise(rb_eArgError, "recursive array");
|
|
|
|
return rb_file_join(arg);
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2017-03-13 12:29:19 +03:00
|
|
|
rb_file_join(VALUE ary)
|
2003-01-06 12:44:15 +03:00
|
|
|
{
|
|
|
|
long len, i;
|
|
|
|
VALUE result, tmp;
|
2008-06-01 23:55:25 +04:00
|
|
|
const char *name, *tail;
|
2012-10-16 09:56:25 +04:00
|
|
|
int checked = TRUE;
|
2012-12-13 09:02:55 +04:00
|
|
|
rb_encoding *enc;
|
2003-01-06 12:44:15 +03:00
|
|
|
|
2006-09-02 18:42:08 +04:00
|
|
|
if (RARRAY_LEN(ary) == 0) return rb_str_new(0, 0);
|
2003-01-06 12:44:15 +03:00
|
|
|
|
|
|
|
len = 1;
|
2006-09-02 18:42:08 +04:00
|
|
|
for (i=0; i<RARRAY_LEN(ary); i++) {
|
2013-05-13 13:56:22 +04:00
|
|
|
tmp = RARRAY_AREF(ary, i);
|
2012-01-25 06:32:06 +04:00
|
|
|
if (RB_TYPE_P(tmp, T_STRING)) {
|
2012-10-16 05:54:05 +04:00
|
|
|
check_path_encoding(tmp);
|
2012-01-25 06:32:06 +04:00
|
|
|
len += RSTRING_LEN(tmp);
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
len += 10;
|
|
|
|
}
|
|
|
|
}
|
2017-03-13 12:29:19 +03:00
|
|
|
len += RARRAY_LEN(ary) - 1;
|
2003-01-06 12:44:15 +03:00
|
|
|
result = rb_str_buf_new(len);
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_CLEAR_CLASS(result);
|
2006-09-02 18:42:08 +04:00
|
|
|
for (i=0; i<RARRAY_LEN(ary); i++) {
|
2013-05-13 13:56:22 +04:00
|
|
|
tmp = RARRAY_AREF(ary, i);
|
2016-10-28 09:58:19 +03:00
|
|
|
switch (OBJ_BUILTIN_TYPE(tmp)) {
|
2003-01-06 12:44:15 +03:00
|
|
|
case T_STRING:
|
2012-10-16 09:56:25 +04:00
|
|
|
if (!checked) check_path_encoding(tmp);
|
2012-10-16 06:27:07 +04:00
|
|
|
StringValueCStr(tmp);
|
2003-01-06 12:44:15 +03:00
|
|
|
break;
|
|
|
|
case T_ARRAY:
|
2009-04-29 10:22:29 +04:00
|
|
|
if (ary == tmp) {
|
|
|
|
rb_raise(rb_eArgError, "recursive array");
|
|
|
|
}
|
|
|
|
else {
|
2017-03-13 12:29:19 +03:00
|
|
|
tmp = rb_exec_recursive(file_inspect_join, ary, tmp);
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2007-12-09 08:12:31 +03:00
|
|
|
FilePathStringValue(tmp);
|
2012-10-16 09:56:25 +04:00
|
|
|
checked = FALSE;
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
2012-10-16 06:27:07 +04:00
|
|
|
RSTRING_GETMEM(result, name, len);
|
2011-10-26 10:24:29 +04:00
|
|
|
if (i == 0) {
|
|
|
|
rb_enc_copy(result, tmp);
|
|
|
|
}
|
2017-03-13 12:29:19 +03:00
|
|
|
else {
|
2012-01-25 06:32:06 +04:00
|
|
|
tail = chompdirsep(name, name + len, rb_enc_get(result));
|
2006-08-31 14:47:44 +04:00
|
|
|
if (RSTRING_PTR(tmp) && isdirsep(RSTRING_PTR(tmp)[0])) {
|
|
|
|
rb_str_set_len(result, tail - name);
|
2005-09-16 17:42:17 +04:00
|
|
|
}
|
|
|
|
else if (!*tail) {
|
2017-03-13 12:29:19 +03:00
|
|
|
rb_str_cat(result, "/", 1);
|
2005-09-16 17:42:17 +04:00
|
|
|
}
|
|
|
|
}
|
2021-01-13 18:14:11 +03:00
|
|
|
enc = fs_enc_check(result, tmp);
|
2003-01-06 12:44:15 +03:00
|
|
|
rb_str_buf_append(result, tmp);
|
2012-12-13 09:02:55 +04:00
|
|
|
rb_enc_associate(result, enc);
|
2003-01-06 12:44:15 +03:00
|
|
|
}
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS_RAW(result, rb_cString);
|
2003-01-06 12:44:15 +03:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2014-06-30 06:37:31 +04:00
|
|
|
* File.join(string, ...) -> string
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns a new string formed by joining the strings using
|
2017-03-13 12:29:19 +03:00
|
|
|
* <code>"/"</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.join("usr", "mail", "gumby") #=> "usr/mail/gumby"
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_join(VALUE klass, VALUE args)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-03-13 12:29:19 +03:00
|
|
|
return rb_file_join(args);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2022-09-05 14:17:05 +03:00
|
|
|
#if defined(HAVE_TRUNCATE)
|
2017-11-19 01:45:11 +03:00
|
|
|
struct truncate_arg {
|
|
|
|
const char *path;
|
2022-09-05 14:23:27 +03:00
|
|
|
rb_off_t pos;
|
2017-11-19 01:45:11 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static void *
|
|
|
|
nogvl_truncate(void *ptr)
|
|
|
|
{
|
|
|
|
struct truncate_arg *ta = ptr;
|
2017-11-19 08:03:22 +03:00
|
|
|
return (void *)(VALUE)truncate(ta->path, ta->pos);
|
2017-11-19 01:45:11 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* File.truncate(file_name, integer) -> 0
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Truncates the file <i>file_name</i> to be at most <i>integer</i>
|
|
|
|
* bytes long. Not available on all platforms.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* f = File.new("out", "w")
|
|
|
|
* f.write("1234567890") #=> 10
|
|
|
|
* f.close #=> nil
|
|
|
|
* File.truncate("out", 5) #=> 0
|
|
|
|
* File.size("out") #=> 5
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_s_truncate(VALUE klass, VALUE path, VALUE len)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-11-19 01:45:11 +03:00
|
|
|
struct truncate_arg ta;
|
|
|
|
int r;
|
2004-11-22 18:26:02 +03:00
|
|
|
|
2022-09-05 14:17:05 +03:00
|
|
|
ta.pos = NUM2OFFT(len);
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(path);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
path = rb_str_encode_ospath(path);
|
2017-11-19 01:45:11 +03:00
|
|
|
ta.path = StringValueCStr(path);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2017-11-19 08:03:22 +03:00
|
|
|
r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_truncate, &ta,
|
|
|
|
RUBY_UBF_IO, NULL);
|
2017-11-19 01:45:11 +03:00
|
|
|
if (r < 0)
|
|
|
|
rb_sys_fail_path(path);
|
1999-01-20 07:59:39 +03:00
|
|
|
return INT2FIX(0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2009-04-16 20:58:06 +04:00
|
|
|
#else
|
|
|
|
#define rb_file_s_truncate rb_f_notimplement
|
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2022-09-05 14:17:05 +03:00
|
|
|
#if defined(HAVE_FTRUNCATE)
|
2017-11-19 01:45:11 +03:00
|
|
|
struct ftruncate_arg {
|
|
|
|
int fd;
|
2022-09-05 14:23:27 +03:00
|
|
|
rb_off_t pos;
|
2017-11-19 01:45:11 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
nogvl_ftruncate(void *ptr)
|
|
|
|
{
|
|
|
|
struct ftruncate_arg *fa = ptr;
|
|
|
|
|
|
|
|
return (VALUE)ftruncate(fa->fd, fa->pos);
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* file.truncate(integer) -> 0
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Truncates <i>file</i> to at most <i>integer</i> bytes. The file
|
|
|
|
* must be opened for writing. Not available on all platforms.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* f = File.new("out", "w")
|
|
|
|
* f.syswrite("1234567890") #=> 10
|
|
|
|
* f.truncate(5) #=> 0
|
|
|
|
* f.close() #=> nil
|
|
|
|
* File.size("out") #=> 5
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_truncate(VALUE obj, VALUE len)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
2017-11-19 01:45:11 +03:00
|
|
|
struct ftruncate_arg fa;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2022-09-05 14:17:05 +03:00
|
|
|
fa.pos = NUM2OFFT(len);
|
1998-01-16 15:13:05 +03:00
|
|
|
GetOpenFile(obj, fptr);
|
|
|
|
if (!(fptr->mode & FMODE_WRITABLE)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_raise(rb_eIOError, "not opened for writing");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2013-08-15 15:53:41 +04:00
|
|
|
rb_io_flush_raw(obj, 0);
|
2017-11-19 01:45:11 +03:00
|
|
|
fa.fd = fptr->fd;
|
|
|
|
if ((int)rb_thread_io_blocking_region(nogvl_ftruncate, &fa, fa.fd) < 0) {
|
2008-08-23 04:47:54 +04:00
|
|
|
rb_sys_fail_path(fptr->pathv);
|
2017-11-19 01:45:11 +03:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
2009-04-16 20:58:06 +04:00
|
|
|
#else
|
|
|
|
#define rb_file_truncate rb_f_notimplement
|
|
|
|
#endif
|
1999-01-20 07:59:39 +03:00
|
|
|
|
|
|
|
# ifndef LOCK_SH
|
|
|
|
# define LOCK_SH 1
|
|
|
|
# endif
|
|
|
|
# ifndef LOCK_EX
|
|
|
|
# define LOCK_EX 2
|
|
|
|
# endif
|
|
|
|
# ifndef LOCK_NB
|
|
|
|
# define LOCK_NB 4
|
|
|
|
# endif
|
|
|
|
# ifndef LOCK_UN
|
|
|
|
# define LOCK_UN 8
|
|
|
|
# endif
|
|
|
|
|
2006-02-06 10:06:22 +03:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
#include <winerror.h>
|
2007-02-24 12:45:41 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static VALUE
|
2007-11-20 13:47:53 +03:00
|
|
|
rb_thread_flock(void *data)
|
2006-02-06 10:06:22 +03:00
|
|
|
{
|
2007-02-24 12:45:41 +03:00
|
|
|
#ifdef __CYGWIN__
|
2006-02-06 10:13:53 +03:00
|
|
|
int old_errno = errno;
|
2007-02-24 12:45:41 +03:00
|
|
|
#endif
|
|
|
|
int *op = data, ret = flock(op[0], op[1]);
|
|
|
|
|
|
|
|
#ifdef __CYGWIN__
|
2006-02-06 10:13:53 +03:00
|
|
|
if (GetLastError() == ERROR_NOT_LOCKED) {
|
2006-02-06 10:06:22 +03:00
|
|
|
ret = 0;
|
2006-02-06 10:13:53 +03:00
|
|
|
errno = old_errno;
|
|
|
|
}
|
2001-03-26 12:57:16 +04:00
|
|
|
#endif
|
2007-02-24 12:45:41 +03:00
|
|
|
return (VALUE)ret;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2023-12-24 00:08:26 +03:00
|
|
|
/* :markup: markdown
|
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* call-seq:
|
2023-12-24 00:08:26 +03:00
|
|
|
* flock(locking_constant) -> 0 or false
|
|
|
|
*
|
|
|
|
* Locks or unlocks a file according to the given `locking_constant`,
|
|
|
|
* a bitwise OR of the values in the table below.
|
|
|
|
*
|
|
|
|
* Not available on all platforms.
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2023-12-24 00:08:26 +03:00
|
|
|
* Returns `false` if `File::LOCK_NB` is specified and the operation would have blocked;
|
|
|
|
* otherwise returns `0`.
|
|
|
|
* <br>
|
|
|
|
*
|
|
|
|
* <table>
|
|
|
|
* <tr>
|
|
|
|
* <th colspan="3">Locking Constants</th>
|
|
|
|
* </tr>
|
|
|
|
* <tr>
|
|
|
|
* <th>Constant</th>
|
|
|
|
* <th>Lock</th>
|
|
|
|
* <th>Effect</th>
|
|
|
|
* </tr>
|
|
|
|
* <tr>
|
|
|
|
* <td><tt>File::LOCK_EX</tt></td>
|
|
|
|
* <td>Exclusive</td>
|
|
|
|
* <td>Only one process may hold an exclusive lock for <tt>self</tt> at a time.</td>
|
|
|
|
* </tr>
|
|
|
|
* <tr>
|
|
|
|
* <td><tt>File::LOCK_NB</tt></td>
|
|
|
|
* <td>Non-blocking</td>
|
|
|
|
* <td>
|
2023-12-24 07:59:34 +03:00
|
|
|
* No blocking; may be combined with other <tt>File::LOCK_SH</tt> or <tt>File::LOCK_EX</tt>
|
2023-12-24 00:08:26 +03:00
|
|
|
* using the bitwise OR operator <tt>|</tt>.
|
|
|
|
* </td>
|
|
|
|
* </tr>
|
|
|
|
* <tr>
|
|
|
|
* <td><tt>File::LOCK_SH</tt></td>
|
|
|
|
* <td>Shared</td>
|
|
|
|
* <td>Multiple processes may each hold a shared lock for <tt>self</tt> at the same time.</td>
|
|
|
|
* </tr>
|
|
|
|
* <tr>
|
|
|
|
* <td><tt>File::LOCK_UN</tt></td>
|
|
|
|
* <td>Unlock</td>
|
|
|
|
* <td>Remove an existing lock held by this process.</td>
|
|
|
|
* </tr>
|
|
|
|
* </table>
|
|
|
|
*
|
|
|
|
* <br>
|
2003-12-21 10:28:54 +03:00
|
|
|
* Example:
|
|
|
|
*
|
2023-12-24 00:08:26 +03:00
|
|
|
* ```ruby
|
|
|
|
* # Update a counter using an exclusive lock.
|
|
|
|
* # Don't use File::WRONLY because it truncates the file.
|
|
|
|
* File.open('counter', File::RDWR | File::CREAT, 0644) do |f|
|
|
|
|
* f.flock(File::LOCK_EX)
|
|
|
|
* value = f.read.to_i + 1
|
|
|
|
* f.rewind
|
|
|
|
* f.write("#{value}\n")
|
|
|
|
* f.flush
|
|
|
|
* f.truncate(f.pos)
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* # Read the counter using a shared lock.
|
|
|
|
* File.open('counter', 'r') do |f|
|
|
|
|
* f.flock(File::LOCK_SH)
|
|
|
|
* f.read
|
|
|
|
* end
|
|
|
|
* ```
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_flock(VALUE obj, VALUE operation)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
* file.c, gc.c, io.c, ruby.h, rubyio.h, win32/win32.h (rb_io_t):
renamed from OpenFile.
* ext/dl/cptr.c, ext/io/wait/wait.c, ext/openssl/ossl.h,
ext/openssl/ossl_bio.c, ext/openssl/ossl_ssl.c, ext/pty/pty.c,
ext/readline/readline.c, ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11869 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-24 13:30:50 +03:00
|
|
|
rb_io_t *fptr;
|
2008-02-28 05:43:59 +03:00
|
|
|
int op[2], op1;
|
2012-12-14 22:08:40 +04:00
|
|
|
struct timeval time;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-02-28 05:43:59 +03:00
|
|
|
op[1] = op1 = NUM2INT(operation);
|
1998-01-16 15:13:05 +03:00
|
|
|
GetOpenFile(obj, fptr);
|
2007-02-24 12:45:41 +03:00
|
|
|
op[0] = fptr->fd;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-01-08 08:00:25 +03:00
|
|
|
if (fptr->mode & FMODE_WRITABLE) {
|
2013-08-16 06:26:28 +04:00
|
|
|
rb_io_flush_raw(obj, 0);
|
2000-01-08 08:00:25 +03:00
|
|
|
}
|
2011-02-20 10:22:57 +03:00
|
|
|
while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
|
|
|
switch (e) {
|
2005-09-20 17:25:59 +04:00
|
|
|
case EAGAIN:
|
|
|
|
case EACCES:
|
2001-03-26 12:57:16 +04:00
|
|
|
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
2005-09-20 17:25:59 +04:00
|
|
|
case EWOULDBLOCK:
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
2008-03-05 11:53:08 +03:00
|
|
|
if (op1 & LOCK_NB) return Qfalse;
|
2012-12-14 22:08:40 +04:00
|
|
|
|
|
|
|
time.tv_sec = 0;
|
|
|
|
time.tv_usec = 100 * 1000; /* 0.1 sec */
|
|
|
|
rb_thread_wait_for(time);
|
2007-02-24 12:45:41 +03:00
|
|
|
rb_io_check_closed(fptr);
|
|
|
|
continue;
|
|
|
|
|
2003-05-01 04:00:37 +04:00
|
|
|
case EINTR:
|
|
|
|
#if defined(ERESTART)
|
|
|
|
case ERESTART:
|
|
|
|
#endif
|
2007-02-24 12:45:41 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, fptr->pathv);
|
2005-09-20 17:25:59 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
return INT2FIX(0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
test_check(int n, int argc, VALUE *argv)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
n+=1;
|
2012-03-15 01:10:34 +04:00
|
|
|
rb_check_arity(argc, n, n);
|
1998-01-16 15:13:05 +03:00
|
|
|
for (i=1; i<n; i++) {
|
2012-04-15 04:06:13 +04:00
|
|
|
if (!RB_TYPE_P(argv[i], T_FILE)) {
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(argv[i]);
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CHECK(n) test_check((n), argc, argv)
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2013-04-24 16:50:12 +04:00
|
|
|
* test(cmd, file1 [, file2] ) -> obj
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2014-02-01 15:08:15 +04:00
|
|
|
* Uses the character +cmd+ to perform various tests on +file1+ (first
|
2012-02-22 03:02:29 +04:00
|
|
|
* table below) or on +file1+ and +file2+ (second table).
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File tests on a single file:
|
|
|
|
*
|
2013-04-24 16:50:12 +04:00
|
|
|
* Cmd Returns Meaning
|
2009-12-07 21:51:42 +03:00
|
|
|
* "A" | Time | Last access time for file1
|
|
|
|
* "b" | boolean | True if file1 is a block device
|
|
|
|
* "c" | boolean | True if file1 is a character device
|
|
|
|
* "C" | Time | Last change time for file1
|
|
|
|
* "d" | boolean | True if file1 exists and is a directory
|
|
|
|
* "e" | boolean | True if file1 exists
|
|
|
|
* "f" | boolean | True if file1 exists and is a regular file
|
2022-10-05 13:35:36 +03:00
|
|
|
* "g" | boolean | True if file1 has the setgid bit set
|
2009-12-07 21:51:42 +03:00
|
|
|
* "G" | boolean | True if file1 exists and has a group
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | ownership equal to the caller's group
|
2009-12-07 21:51:42 +03:00
|
|
|
* "k" | boolean | True if file1 exists and has the sticky bit set
|
|
|
|
* "l" | boolean | True if file1 exists and is a symbolic link
|
|
|
|
* "M" | Time | Last modification time for file1
|
|
|
|
* "o" | boolean | True if file1 exists and is owned by
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | the caller's effective uid
|
2009-12-07 21:51:42 +03:00
|
|
|
* "O" | boolean | True if file1 exists and is owned by
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | the caller's real uid
|
2009-12-07 21:51:42 +03:00
|
|
|
* "p" | boolean | True if file1 exists and is a fifo
|
|
|
|
* "r" | boolean | True if file1 is readable by the effective
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | uid/gid of the caller
|
2009-12-07 21:51:42 +03:00
|
|
|
* "R" | boolean | True if file is readable by the real
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | uid/gid of the caller
|
2009-12-07 21:51:42 +03:00
|
|
|
* "s" | int/nil | If file1 has nonzero size, return the size,
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | otherwise return nil
|
2009-12-07 21:51:42 +03:00
|
|
|
* "S" | boolean | True if file1 exists and is a socket
|
|
|
|
* "u" | boolean | True if file1 has the setuid bit set
|
|
|
|
* "w" | boolean | True if file1 exists and is writable by
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | the effective uid/gid
|
2009-12-07 21:51:42 +03:00
|
|
|
* "W" | boolean | True if file1 exists and is writable by
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | the real uid/gid
|
2009-12-07 21:51:42 +03:00
|
|
|
* "x" | boolean | True if file1 exists and is executable by
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | the effective uid/gid
|
2009-12-07 21:51:42 +03:00
|
|
|
* "X" | boolean | True if file1 exists and is executable by
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | the real uid/gid
|
2009-12-07 21:51:42 +03:00
|
|
|
* "z" | boolean | True if file1 exists and has a zero length
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2012-02-22 03:02:29 +04:00
|
|
|
* Tests that take two files:
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
2009-12-07 21:51:42 +03:00
|
|
|
* "-" | boolean | True if file1 and file2 are identical
|
|
|
|
* "=" | boolean | True if the modification times of file1
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | and file2 are equal
|
2009-12-07 21:51:42 +03:00
|
|
|
* "<" | boolean | True if the modification time of file1
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | is prior to that of file2
|
2009-12-07 21:51:42 +03:00
|
|
|
* ">" | boolean | True if the modification time of file1
|
2003-12-21 10:28:54 +03:00
|
|
|
* | | is after that of file2
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_f_test(int argc, VALUE *argv, VALUE _)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
int cmd;
|
|
|
|
|
2012-03-15 01:10:34 +04:00
|
|
|
if (argc == 0) rb_check_arity(argc, 2, 3);
|
1999-01-20 07:59:39 +03:00
|
|
|
cmd = NUM2CHR(argv[0]);
|
2012-04-15 04:06:13 +04:00
|
|
|
if (cmd == 0) {
|
2020-06-15 08:27:29 +03:00
|
|
|
goto unknown;
|
2012-04-15 04:06:13 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
|
|
|
|
CHECK(1);
|
|
|
|
switch (cmd) {
|
|
|
|
case 'b':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_blockdev_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'c':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_chardev_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'd':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_directory_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'e':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_exist_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'f':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_file_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'g':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_sgid_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'G':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_grpowned_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'k':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_sticky_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'l':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_symlink_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'o':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_owned_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'O':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_rowned_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'p':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_pipe_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'r':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_readable_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'R':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_readable_real_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 's':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_size_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'S':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_socket_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'u':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_suid_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'w':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_writable_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'W':
|
2010-06-05 03:30:48 +04:00
|
|
|
return rb_file_writable_real_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'x':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_executable_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'X':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_executable_real_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
case 'z':
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_zero_p(0, argv[1]);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr("MAC", cmd)) {
|
|
|
|
struct stat st;
|
2009-01-05 02:59:20 +03:00
|
|
|
VALUE fname = argv[1];
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
CHECK(1);
|
2009-01-05 02:59:20 +03:00
|
|
|
if (rb_stat(fname, &st) == -1) {
|
2015-12-23 11:57:48 +03:00
|
|
|
int e = errno;
|
2009-01-05 02:59:20 +03:00
|
|
|
FilePathValue(fname);
|
2015-12-23 11:57:48 +03:00
|
|
|
rb_syserr_fail_path(e, fname);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
switch (cmd) {
|
|
|
|
case 'A':
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_atime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'M':
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_mtime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'C':
|
* configure.in: check struct timespec, clock_gettime, utimensat,
struct stat.st_atim,
struct stat.st_atimespec,
struct stat.st_atimensec,
struct stat.st_mtim,
struct stat.st_mtimespec,
struct stat.st_mtimensec,
struct stat.st_ctim,
struct stat.st_ctimespec,
struct stat.st_ctimensec.
* include/ruby/missing.h: provide struct timespec if not available.
* time.c: support nanosecond-resolution using struct timespec.
* include/ruby/intern.h: provide rb_time_nano_new.
* file.c (utime_internal): use utimensat if available.
(rb_file_s_utime): refactored.
(rb_f_test): use stat_atime, stat_mtime, stat_ctime.
(rb_stat_cmp): check tv_nsec.
(stat_atimespec): new function.
(stat_atime): ditto.
(stat_mtimespec): ditto.
(stat_mtime): ditto.
(stat_ctimespec): ditto.
(stat_ctime): ditto.
(rb_stat_atime): use stat_atime.
(rb_file_s_atime): ditto.
(rb_file_atime): ditto.
(rb_stat_mtime): use stat_mtime.
(rb_file_s_mtime): ditto.
(rb_file_mtime): ditto.
(rb_file_ctime): use stat_ctime.
(rb_file_s_ctime): ditto.
(rb_stat_ctime): ditto.
* variable.c (rb_copy_generic_ivar): clear clone's instance variables
if obj has no instance variable.
* marshal.c (w_object): dump instance variables of generated string
for TYPE_USERDEF, even if original object has instance variables.
* lib/time.rb (Time#xmlschema): use nsec instead of usec.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-11-19 12:09:38 +03:00
|
|
|
return stat_ctime(&st);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-22 19:26:39 +03:00
|
|
|
if (cmd == '-') {
|
|
|
|
CHECK(2);
|
2006-12-07 18:18:14 +03:00
|
|
|
return rb_file_identical_p(0, argv[1], argv[2]);
|
2005-11-22 19:26:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr("=<>", cmd)) {
|
1998-01-16 15:13:05 +03:00
|
|
|
struct stat st1, st2;
|
2015-04-11 17:34:26 +03:00
|
|
|
struct timespec t1, t2;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
CHECK(2);
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_stat(argv[1], &st1) < 0) return Qfalse;
|
|
|
|
if (rb_stat(argv[2], &st2) < 0) return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2015-04-11 17:34:26 +03:00
|
|
|
t1 = stat_mtimespec(&st1);
|
|
|
|
t2 = stat_mtimespec(&st2);
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
switch (cmd) {
|
|
|
|
case '=':
|
2015-04-11 17:34:26 +03:00
|
|
|
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec) return Qtrue;
|
1999-10-12 08:53:36 +04:00
|
|
|
return Qfalse;
|
2001-07-16 08:22:46 +04:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case '>':
|
2015-04-11 17:34:26 +03:00
|
|
|
if (t1.tv_sec > t2.tv_sec) return Qtrue;
|
|
|
|
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec) return Qtrue;
|
1999-10-12 08:53:36 +04:00
|
|
|
return Qfalse;
|
2001-07-16 08:22:46 +04:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case '<':
|
2015-04-11 17:34:26 +03:00
|
|
|
if (t1.tv_sec < t2.tv_sec) return Qtrue;
|
|
|
|
if (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec) return Qtrue;
|
1999-10-12 08:53:36 +04:00
|
|
|
return Qfalse;
|
2005-09-20 17:25:59 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2020-06-15 08:27:29 +03:00
|
|
|
unknown:
|
|
|
|
/* unknown command */
|
|
|
|
if (ISPRINT(cmd)) {
|
|
|
|
rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
|
|
|
|
}
|
2020-06-24 10:23:59 +03:00
|
|
|
UNREACHABLE_RETURN(Qundef);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Document-class: File::Stat
|
|
|
|
*
|
2019-03-22 14:04:59 +03:00
|
|
|
* Objects of class File::Stat encapsulate common status information
|
|
|
|
* for File objects. The information is recorded at the moment the
|
|
|
|
* File::Stat object is created; changes made to the file after that
|
|
|
|
* point will not be reflected. File::Stat objects are returned by
|
|
|
|
* IO#stat, File::stat, File#lstat, and File::lstat. Many of these
|
2003-12-21 10:28:54 +03:00
|
|
|
* methods return platform-specific values, and not all values are
|
2019-03-22 14:04:59 +03:00
|
|
|
* meaningful on all systems. See also Kernel#test.
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2001-05-02 08:22:21 +04:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_s_alloc(VALUE klass)
|
2001-05-02 08:22:21 +04:00
|
|
|
{
|
2001-10-03 11:19:19 +04:00
|
|
|
return stat_new_0(klass, 0);
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
*
|
2010-05-18 01:31:22 +04:00
|
|
|
* File::Stat.new(file_name) -> stat
|
2003-12-21 10:28:54 +03:00
|
|
|
*
|
|
|
|
* Create a File::Stat object for the given file name (raising an
|
|
|
|
* exception if the file doesn't exist).
|
|
|
|
*/
|
|
|
|
|
2001-10-03 11:19:19 +04:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_init(VALUE obj, VALUE fname)
|
2001-10-03 11:19:19 +04:00
|
|
|
{
|
2023-11-22 15:36:10 +03:00
|
|
|
struct stat st;
|
2001-05-02 08:22:21 +04:00
|
|
|
|
2004-04-07 10:30:15 +04:00
|
|
|
FilePathValue(fname);
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
fname = rb_str_encode_ospath(fname);
|
|
|
|
if (STAT(StringValueCStr(fname), &st) == -1) {
|
2012-02-24 11:37:48 +04:00
|
|
|
rb_sys_fail_path(fname);
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
2022-11-18 01:50:25 +03:00
|
|
|
|
2023-11-22 15:36:10 +03:00
|
|
|
struct rb_stat *rb_st;
|
|
|
|
TypedData_Get_Struct(obj, struct rb_stat, &stat_data_type, rb_st);
|
|
|
|
|
|
|
|
rb_st->stat = st;
|
|
|
|
rb_st->initialized = true;
|
2001-05-02 08:22:21 +04:00
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2004-01-18 17:16:47 +03:00
|
|
|
/* :nodoc: */
|
2001-10-10 12:21:13 +04:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_init_copy(VALUE copy, VALUE orig)
|
2001-10-10 12:21:13 +04:00
|
|
|
{
|
2012-06-05 15:13:18 +04:00
|
|
|
if (!OBJ_INIT_COPY(copy, orig)) return copy;
|
2001-10-10 12:21:13 +04:00
|
|
|
|
2023-11-22 15:36:10 +03:00
|
|
|
struct rb_stat *orig_rb_st;
|
|
|
|
TypedData_Get_Struct(orig, struct rb_stat, &stat_data_type, orig_rb_st);
|
|
|
|
|
|
|
|
struct rb_stat *copy_rb_st;
|
|
|
|
TypedData_Get_Struct(copy, struct rb_stat, &stat_data_type, copy_rb_st);
|
|
|
|
|
|
|
|
*copy_rb_st = *orig_rb_st;
|
2002-09-03 09:20:14 +04:00
|
|
|
return copy;
|
2001-10-10 12:21:13 +04:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.ftype -> string
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Identifies the type of <i>stat</i>. The return string is one of:
|
|
|
|
* ``<code>file</code>'', ``<code>directory</code>'',
|
|
|
|
* ``<code>characterSpecial</code>'', ``<code>blockSpecial</code>'',
|
|
|
|
* ``<code>fifo</code>'', ``<code>link</code>'',
|
|
|
|
* ``<code>socket</code>'', or ``<code>unknown</code>''.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("/dev/tty").ftype #=> "characterSpecial"
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_ftype(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-07 12:25:55 +03:00
|
|
|
return rb_file_ftype(get_stat(obj));
|
1999-11-25 12:03:08 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.directory? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is a directory,
|
|
|
|
* <code>false</code> otherwise.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").directory? #=> false
|
|
|
|
* File.stat(".").directory? #=> true
|
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_d(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-01 12:24:48 +03:00
|
|
|
if (S_ISDIR(get_stat(obj)->st_mode)) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.pipe? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if the operating system supports pipes and
|
|
|
|
* <i>stat</i> is a pipe; <code>false</code> otherwise.
|
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_p(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
|
|
|
#ifdef S_IFIFO
|
1999-12-01 12:24:48 +03:00
|
|
|
if (S_ISFIFO(get_stat(obj)->st_mode)) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
|
|
|
|
#endif
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.symlink? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is a symbolic link,
|
|
|
|
* <code>false</code> if it isn't or if the operating system doesn't
|
2019-03-22 14:04:59 +03:00
|
|
|
* support this feature. As File::stat automatically follows symbolic
|
|
|
|
* links, #symlink? will always be <code>false</code> for an object
|
|
|
|
* returned by File::stat.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.symlink("testfile", "alink") #=> 0
|
|
|
|
* File.stat("alink").symlink? #=> false
|
|
|
|
* File.lstat("alink").symlink? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_l(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
|
|
|
#ifdef S_ISLNK
|
1999-12-01 12:24:48 +03:00
|
|
|
if (S_ISLNK(get_stat(obj)->st_mode)) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.socket? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is a socket,
|
|
|
|
* <code>false</code> if it isn't or if the operating system doesn't
|
|
|
|
* support this feature.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").socket? #=> false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_S(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
|
|
|
#ifdef S_ISSOCK
|
1999-12-01 12:24:48 +03:00
|
|
|
if (S_ISSOCK(get_stat(obj)->st_mode)) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
|
|
|
|
#endif
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.blockdev? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if the file is a block device,
|
|
|
|
* <code>false</code> if it isn't or if the operating system doesn't
|
|
|
|
* support this feature.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").blockdev? #=> false
|
|
|
|
* File.stat("/dev/hda1").blockdev? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_b(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
|
|
|
#ifdef S_ISBLK
|
1999-12-01 12:24:48 +03:00
|
|
|
if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
|
|
|
|
#endif
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.chardev? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if the file is a character device,
|
|
|
|
* <code>false</code> if it isn't or if the operating system doesn't
|
|
|
|
* support this feature.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("/dev/tty").chardev? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_c(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
2000-02-01 06:12:21 +03:00
|
|
|
if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.owned? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if the effective user id of the process is
|
|
|
|
* the same as the owner of <i>stat</i>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").owned? #=> true
|
|
|
|
* File.stat("/etc/passwd").owned? #=> false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_owned(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-01 12:24:48 +03:00
|
|
|
if (get_stat(obj)->st_uid == geteuid()) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_rowned(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-01 12:24:48 +03:00
|
|
|
if (get_stat(obj)->st_uid == getuid()) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.grpowned? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns true if the effective group id of the process is the same as
|
2022-10-05 13:35:36 +03:00
|
|
|
* the group id of <i>stat</i>. On Windows, returns <code>false</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").grpowned? #=> true
|
|
|
|
* File.stat("/etc/passwd").grpowned? #=> false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_grpowned(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-15 06:18:08 +03:00
|
|
|
#ifndef _WIN32
|
2010-02-16 15:00:24 +03:00
|
|
|
if (rb_group_member(get_stat(obj)->st_gid)) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.readable? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is readable by the
|
|
|
|
* effective user id of this process.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").readable? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_r(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-06 12:04:03 +03:00
|
|
|
struct stat *st = get_stat(obj);
|
1999-11-25 12:03:08 +03:00
|
|
|
|
2006-08-17 14:15:55 +04:00
|
|
|
#ifdef USE_GETEUID
|
|
|
|
if (geteuid() == 0) return Qtrue;
|
|
|
|
#endif
|
1999-11-25 12:03:08 +03:00
|
|
|
#ifdef S_IRUSR
|
|
|
|
if (rb_stat_owned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IRUSR);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
#ifdef S_IRGRP
|
|
|
|
if (rb_stat_grpowned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IRGRP);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
#ifdef S_IROTH
|
1999-12-06 12:04:03 +03:00
|
|
|
if (!(st->st_mode & S_IROTH)) return Qfalse;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.readable_real? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is readable by the real
|
|
|
|
* user id of this process.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").readable_real? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_R(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-06 12:04:03 +03:00
|
|
|
struct stat *st = get_stat(obj);
|
1999-11-25 12:03:08 +03:00
|
|
|
|
2006-08-17 14:15:55 +04:00
|
|
|
#ifdef USE_GETEUID
|
|
|
|
if (getuid() == 0) return Qtrue;
|
|
|
|
#endif
|
1999-11-25 12:03:08 +03:00
|
|
|
#ifdef S_IRUSR
|
|
|
|
if (rb_stat_rowned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IRUSR);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
#ifdef S_IRGRP
|
2010-02-16 15:00:24 +03:00
|
|
|
if (rb_group_member(get_stat(obj)->st_gid))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IRGRP);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
#ifdef S_IROTH
|
1999-12-06 12:04:03 +03:00
|
|
|
if (!(st->st_mode & S_IROTH)) return Qfalse;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
2004-01-19 12:19:31 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.world_readable? -> integer or nil
|
2004-01-19 12:19:31 +03:00
|
|
|
*
|
|
|
|
* If <i>stat</i> is readable by others, returns an integer
|
|
|
|
* representing the file permission bits of <i>stat</i>. Returns
|
|
|
|
* <code>nil</code> otherwise. The meaning of the bits is platform
|
|
|
|
* dependent; on Unix systems, see <code>stat(2)</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2010-05-18 01:07:33 +04:00
|
|
|
* m = File.stat("/etc/passwd").world_readable? #=> 420
|
|
|
|
* sprintf("%o", m) #=> "644"
|
2004-01-19 12:19:31 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_wr(VALUE obj)
|
2004-01-19 12:19:31 +03:00
|
|
|
{
|
|
|
|
#ifdef S_IROTH
|
2015-12-08 18:52:40 +03:00
|
|
|
struct stat *st = get_stat(obj);
|
|
|
|
if ((st->st_mode & (S_IROTH)) == S_IROTH) {
|
|
|
|
return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
|
2004-01-19 12:19:31 +03:00
|
|
|
}
|
|
|
|
#endif
|
2023-03-22 12:42:53 +03:00
|
|
|
return Qnil;
|
2004-01-19 12:19:31 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.writable? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is writable by the
|
|
|
|
* effective user id of this process.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").writable? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_w(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-06 12:04:03 +03:00
|
|
|
struct stat *st = get_stat(obj);
|
1999-11-25 12:03:08 +03:00
|
|
|
|
2006-08-17 14:15:55 +04:00
|
|
|
#ifdef USE_GETEUID
|
|
|
|
if (geteuid() == 0) return Qtrue;
|
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IWUSR
|
1999-11-25 12:03:08 +03:00
|
|
|
if (rb_stat_owned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IWUSR);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IWGRP
|
1999-11-25 12:03:08 +03:00
|
|
|
if (rb_stat_grpowned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IWGRP);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IWOTH
|
|
|
|
if (!(st->st_mode & S_IWOTH)) return Qfalse;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.writable_real? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is writable by the real
|
|
|
|
* user id of this process.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").writable_real? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_W(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-06 12:04:03 +03:00
|
|
|
struct stat *st = get_stat(obj);
|
1999-11-25 12:03:08 +03:00
|
|
|
|
2006-08-17 14:15:55 +04:00
|
|
|
#ifdef USE_GETEUID
|
|
|
|
if (getuid() == 0) return Qtrue;
|
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IWUSR
|
1999-11-25 12:03:08 +03:00
|
|
|
if (rb_stat_rowned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IWUSR);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IWGRP
|
2010-02-16 15:00:24 +03:00
|
|
|
if (rb_group_member(get_stat(obj)->st_gid))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IWGRP);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IWOTH
|
|
|
|
if (!(st->st_mode & S_IWOTH)) return Qfalse;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
2004-01-19 12:19:31 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-08 07:57:49 +03:00
|
|
|
* stat.world_writable? -> integer or nil
|
2004-01-19 12:19:31 +03:00
|
|
|
*
|
|
|
|
* If <i>stat</i> is writable by others, returns an integer
|
|
|
|
* representing the file permission bits of <i>stat</i>. Returns
|
|
|
|
* <code>nil</code> otherwise. The meaning of the bits is platform
|
|
|
|
* dependent; on Unix systems, see <code>stat(2)</code>.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2010-05-18 01:07:33 +04:00
|
|
|
* m = File.stat("/tmp").world_writable? #=> 511
|
|
|
|
* sprintf("%o", m) #=> "777"
|
2004-01-19 12:19:31 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_ww(VALUE obj)
|
2004-01-19 12:19:31 +03:00
|
|
|
{
|
2023-03-20 11:28:24 +03:00
|
|
|
#ifdef S_IWOTH
|
2015-12-08 18:52:40 +03:00
|
|
|
struct stat *st = get_stat(obj);
|
|
|
|
if ((st->st_mode & (S_IWOTH)) == S_IWOTH) {
|
|
|
|
return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
|
2004-01-19 12:19:31 +03:00
|
|
|
}
|
|
|
|
#endif
|
2023-03-22 12:42:53 +03:00
|
|
|
return Qnil;
|
2004-01-19 12:19:31 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.executable? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is executable or if the
|
|
|
|
* operating system doesn't distinguish executable files from
|
|
|
|
* nonexecutable files. The tests are made using the effective owner of
|
|
|
|
* the process.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").executable? #=> false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_x(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-06 12:04:03 +03:00
|
|
|
struct stat *st = get_stat(obj);
|
1999-11-25 12:03:08 +03:00
|
|
|
|
2006-08-17 14:15:55 +04:00
|
|
|
#ifdef USE_GETEUID
|
|
|
|
if (geteuid() == 0) {
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IXUGO);
|
2006-08-17 14:15:55 +04:00
|
|
|
}
|
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IXUSR
|
1999-11-25 12:03:08 +03:00
|
|
|
if (rb_stat_owned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IXUSR);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IXGRP
|
1999-11-25 12:03:08 +03:00
|
|
|
if (rb_stat_grpowned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IXGRP);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IXOTH
|
|
|
|
if (!(st->st_mode & S_IXOTH)) return Qfalse;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.executable_real? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Same as <code>executable?</code>, but tests using the real owner of
|
|
|
|
* the process.
|
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_X(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-06 12:04:03 +03:00
|
|
|
struct stat *st = get_stat(obj);
|
1999-11-25 12:03:08 +03:00
|
|
|
|
2006-08-17 14:15:55 +04:00
|
|
|
#ifdef USE_GETEUID
|
|
|
|
if (getuid() == 0) {
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IXUGO);
|
2006-08-17 14:15:55 +04:00
|
|
|
}
|
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IXUSR
|
1999-11-25 12:03:08 +03:00
|
|
|
if (rb_stat_rowned(obj))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IXUSR);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IXGRP
|
2010-02-16 15:00:24 +03:00
|
|
|
if (rb_group_member(get_stat(obj)->st_gid))
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(st->st_mode & S_IXGRP);
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
1999-12-06 12:04:03 +03:00
|
|
|
#ifdef S_IXOTH
|
|
|
|
if (!(st->st_mode & S_IXOTH)) return Qfalse;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.file? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is a regular file (not
|
|
|
|
* a device file, pipe, socket, etc.).
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").file? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_f(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-01 12:24:48 +03:00
|
|
|
if (S_ISREG(get_stat(obj)->st_mode)) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.zero? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> is a zero-length file;
|
|
|
|
* <code>false</code> otherwise.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").zero? #=> false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_z(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
1999-12-01 12:24:48 +03:00
|
|
|
if (get_stat(obj)->st_size == 0) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2021-08-17 15:44:41 +03:00
|
|
|
* stat.size? -> Integer or nil
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2021-08-17 15:44:41 +03:00
|
|
|
* Returns +nil+ if <i>stat</i> is a zero-length file, the size of
|
|
|
|
* the file otherwise.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2021-08-17 15:44:41 +03:00
|
|
|
* File.stat("testfile").size? #=> 66
|
2023-07-10 13:18:48 +03:00
|
|
|
* File.stat(File::NULL).size? #=> nil
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_s(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
2022-09-05 14:23:27 +03:00
|
|
|
rb_off_t size = get_stat(obj)->st_size;
|
1999-11-25 12:03:08 +03:00
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
if (size == 0) return Qnil;
|
2002-08-28 12:05:23 +04:00
|
|
|
return OFFT2NUM(size);
|
1999-11-25 12:03:08 +03:00
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.setuid? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> has the set-user-id
|
|
|
|
* permission bit set, <code>false</code> if it doesn't or if the
|
|
|
|
* operating system doesn't support this feature.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("/bin/su").setuid? #=> true
|
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_suid(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
|
|
|
#ifdef S_ISUID
|
1999-12-01 12:24:48 +03:00
|
|
|
if (get_stat(obj)->st_mode & S_ISUID) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.setgid? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> has the set-group-id
|
|
|
|
* permission bit set, <code>false</code> if it doesn't or if the
|
|
|
|
* operating system doesn't support this feature.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("/usr/sbin/lpc").setgid? #=> true
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_sgid(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
2000-05-13 20:13:31 +04:00
|
|
|
#ifdef S_ISGID
|
1999-12-01 12:24:48 +03:00
|
|
|
if (get_stat(obj)->st_mode & S_ISGID) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-12-21 10:28:54 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:31:22 +04:00
|
|
|
* stat.sticky? -> true or false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* Returns <code>true</code> if <i>stat</i> has its sticky bit set,
|
|
|
|
* <code>false</code> if it doesn't or if the operating system doesn't
|
|
|
|
* support this feature.
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
* File.stat("testfile").sticky? #=> false
|
2009-02-18 06:04:49 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
1999-11-25 12:03:08 +03:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_stat_sticky(VALUE obj)
|
1999-11-25 12:03:08 +03:00
|
|
|
{
|
|
|
|
#ifdef S_ISVTX
|
1999-12-01 12:24:48 +03:00
|
|
|
if (get_stat(obj)->st_mode & S_ISVTX) return Qtrue;
|
1999-11-25 12:03:08 +03:00
|
|
|
#endif
|
2000-06-12 11:48:31 +04:00
|
|
|
return Qfalse;
|
1999-11-25 12:03:08 +03:00
|
|
|
}
|
|
|
|
|
2015-09-18 14:11:14 +03:00
|
|
|
#if !defined HAVE_MKFIFO && defined HAVE_MKNOD && defined S_IFIFO
|
|
|
|
#define mkfifo(path, mode) mknod(path, (mode)&~S_IFMT|S_IFIFO, 0)
|
|
|
|
#define HAVE_MKFIFO
|
|
|
|
#endif
|
|
|
|
|
2017-07-29 15:11:51 +03:00
|
|
|
#ifdef HAVE_MKFIFO
|
2017-11-20 05:29:35 +03:00
|
|
|
struct mkfifo_arg {
|
|
|
|
const char *path;
|
|
|
|
mode_t mode;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *
|
|
|
|
nogvl_mkfifo(void *ptr)
|
|
|
|
{
|
|
|
|
struct mkfifo_arg *ma = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)mkfifo(ma->path, ma->mode);
|
|
|
|
}
|
|
|
|
|
2015-09-18 14:11:14 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-01-19 21:42:36 +03:00
|
|
|
* File.mkfifo(file_name, mode=0666) => 0
|
2015-09-18 14:11:14 +03:00
|
|
|
*
|
|
|
|
* Creates a FIFO special file with name _file_name_. _mode_
|
|
|
|
* specifies the FIFO's permissions. It is modified by the process's
|
|
|
|
* umask in the usual way: the permissions of the created file are
|
|
|
|
* (mode & ~umask).
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_file_s_mkfifo(int argc, VALUE *argv, VALUE _)
|
2015-09-18 14:11:14 +03:00
|
|
|
{
|
|
|
|
VALUE path;
|
2017-11-20 05:29:35 +03:00
|
|
|
struct mkfifo_arg ma;
|
2015-09-18 14:11:14 +03:00
|
|
|
|
2017-11-20 05:29:35 +03:00
|
|
|
ma.mode = 0666;
|
2015-09-18 14:11:14 +03:00
|
|
|
rb_check_arity(argc, 1, 2);
|
|
|
|
if (argc > 1) {
|
2017-11-20 05:29:35 +03:00
|
|
|
ma.mode = NUM2MODET(argv[1]);
|
2015-09-18 14:11:14 +03:00
|
|
|
}
|
|
|
|
path = argv[0];
|
|
|
|
FilePathValue(path);
|
|
|
|
path = rb_str_encode_ospath(path);
|
2017-11-20 05:29:35 +03:00
|
|
|
ma.path = RSTRING_PTR(path);
|
|
|
|
if (rb_thread_call_without_gvl(nogvl_mkfifo, &ma, RUBY_UBF_IO, 0)) {
|
2015-09-18 14:11:14 +03:00
|
|
|
rb_sys_fail_path(path);
|
|
|
|
}
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define rb_file_s_mkfifo rb_f_notimplement
|
|
|
|
#endif
|
|
|
|
|
ruby/ruby.h: remove unnecessary exports from C-API
Needlessly exporting can reduce performance locally and increase
binary size.
Increasing the footprint of our C-API larger is also detrimental
to our development as it encourages tighter coupling with our
internals; making it harder for us to preserve compatibility.
If some parts of the core codebase needs access to globals,
internal.h should be used instead of anything in include/ruby/*.
"Urabe, Shyouhei" <shyouhei@ruby-lang.org> wrote:
> On Thu, Jan 18, 2018 at 7:33 PM, Eric Wong <normalperson@yhbt.net> wrote:
> > shyouhei@ruby-lang.org wrote:
> >> https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61908
> >>
> >> export rb_mFConst
> >
> > Why are we exporting all these and making the public C-API bigger?
> > If anything, we should make these static. Thanks.
>
> No concrete reason, except they have already been externed in 2.5.
> These variables had lacked declarations so far, which resulted in their
> visibility to be that of extern. The commit is just confirming the status quo.
>
> I'm not against to turn them into static.
This reverts changes from r61910, r61909, r61908, r61907, and r61906.
* transcode.c (rb_eUndefinedConversionError): make static
(rb_eInvalidByteSequenceError): ditto
(rb_eConverterNotFoundError): ditto
* process.c (rb_mProcGID, rb_mProcUid, rb_mProcID_Syscall): ditto
* file.c (rb_mFConst): ditto
* error.c (rb_mWarning, rb_cWarningBuffer): ditto
* enumerator.c (rb_cLazy): ditto
[Misc #14381]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-25 00:07:14 +03:00
|
|
|
static VALUE rb_mFConst;
|
1999-08-13 09:45:20 +04:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_file_const(const char *name, VALUE value)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2000-09-25 13:15:08 +04:00
|
|
|
rb_define_const(rb_mFConst, name, value);
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2010-03-13 04:34:38 +03:00
|
|
|
int
|
|
|
|
rb_is_absolute_path(const char *path)
|
2000-01-05 07:41:21 +03:00
|
|
|
{
|
2003-02-12 17:56:45 +03:00
|
|
|
#ifdef DOSISH_DRIVE_LETTER
|
2003-02-16 13:22:36 +03:00
|
|
|
if (has_drive_letter(path) && isdirsep(path[2])) return 1;
|
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-15 06:18:08 +03:00
|
|
|
#endif
|
2003-02-12 17:56:45 +03:00
|
|
|
#ifdef DOSISH_UNC
|
2001-07-24 19:11:02 +04:00
|
|
|
if (isdirsep(path[0]) && isdirsep(path[1])) return 1;
|
2002-08-20 14:42:57 +04:00
|
|
|
#endif
|
|
|
|
#ifndef DOSISH
|
2000-01-05 07:41:21 +03:00
|
|
|
if (path[0] == '/') return 1;
|
2001-07-24 19:11:02 +04:00
|
|
|
#endif
|
2000-01-05 07:41:21 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-09-07 18:28:36 +04:00
|
|
|
#ifndef ENABLE_PATH_CHECK
|
|
|
|
# if defined DOSISH || defined __CYGWIN__
|
|
|
|
# define ENABLE_PATH_CHECK 0
|
|
|
|
# else
|
|
|
|
# define ENABLE_PATH_CHECK 1
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if ENABLE_PATH_CHECK
|
2000-01-05 07:41:21 +03:00
|
|
|
static int
|
2020-06-23 03:32:59 +03:00
|
|
|
path_check_0(VALUE path)
|
2000-01-05 07:41:21 +03:00
|
|
|
{
|
|
|
|
struct stat st;
|
2008-06-01 23:55:25 +04:00
|
|
|
const char *p0 = StringValueCStr(path);
|
2012-01-25 06:32:06 +04:00
|
|
|
const char *e0;
|
|
|
|
rb_encoding *enc;
|
2001-11-08 12:21:59 +03:00
|
|
|
char *p = 0, *s;
|
2001-11-08 09:43:14 +03:00
|
|
|
|
2010-03-13 04:34:38 +03:00
|
|
|
if (!rb_is_absolute_path(p0)) {
|
2017-11-26 04:36:33 +03:00
|
|
|
char *buf = ruby_getcwd();
|
2001-11-08 09:43:14 +03:00
|
|
|
VALUE newpath;
|
2000-01-05 07:41:21 +03:00
|
|
|
|
2001-11-08 09:43:14 +03:00
|
|
|
newpath = rb_str_new2(buf);
|
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 14:01:40 +04:00
|
|
|
xfree(buf);
|
2000-01-05 07:41:21 +03:00
|
|
|
|
2001-11-08 09:43:14 +03:00
|
|
|
rb_str_cat2(newpath, "/");
|
|
|
|
rb_str_cat2(newpath, p0);
|
2009-10-10 18:57:46 +04:00
|
|
|
path = newpath;
|
|
|
|
p0 = RSTRING_PTR(path);
|
2000-01-05 07:41:21 +03:00
|
|
|
}
|
2012-01-25 06:32:06 +04:00
|
|
|
e0 = p0 + RSTRING_LEN(path);
|
|
|
|
enc = rb_enc_get(path);
|
2000-01-05 07:41:21 +03:00
|
|
|
for (;;) {
|
2002-02-19 09:43:58 +03:00
|
|
|
#ifndef S_IWOTH
|
|
|
|
# define S_IWOTH 002
|
|
|
|
#endif
|
* merge some patches from win32-uncode-test branch.
see #1685.
* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
to convert encoding for pathname.
* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
accept UTF-8 path.
* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
rb_w32_unlink): use WCHAR path internally.
* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
functions on Win32.
* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
rb_str_encode_ospath() before passing the path to system.
* io.c (rb_sysopen): ditto.
* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-04-30 21:56:23 +04:00
|
|
|
if (STAT(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
|
2002-02-19 09:43:58 +03:00
|
|
|
#ifdef S_ISVTX
|
2020-06-23 03:32:59 +03:00
|
|
|
&& !(p && (st.st_mode & S_ISVTX))
|
2002-02-19 09:43:58 +03:00
|
|
|
#endif
|
2004-06-04 13:56:25 +04:00
|
|
|
&& !access(p0, W_OK)) {
|
2020-06-23 03:32:59 +03:00
|
|
|
rb_enc_warn(enc, "Insecure world writable dir %s in PATH, mode 0%"
|
2021-04-12 08:42:26 +03:00
|
|
|
#if SIZEOF_DEV_T > SIZEOF_INT
|
2017-06-03 17:40:05 +03:00
|
|
|
PRI_MODET_PREFIX"o",
|
2021-04-12 08:42:26 +03:00
|
|
|
#else
|
|
|
|
"o",
|
|
|
|
#endif
|
2020-06-23 03:32:59 +03:00
|
|
|
p0, st.st_mode);
|
2001-07-24 19:11:02 +04:00
|
|
|
if (p) *p = '/';
|
2009-10-10 18:57:46 +04:00
|
|
|
RB_GC_GUARD(path);
|
2000-01-05 07:41:21 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2012-01-25 06:32:06 +04:00
|
|
|
s = strrdirsep(p0, e0, enc);
|
2000-01-05 07:41:21 +03:00
|
|
|
if (p) *p = '/';
|
2001-11-08 09:43:14 +03:00
|
|
|
if (!s || s == p0) return 1;
|
2000-01-05 07:41:21 +03:00
|
|
|
p = s;
|
2012-01-25 06:32:06 +04:00
|
|
|
e0 = p;
|
2000-01-05 07:41:21 +03:00
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
}
|
2002-09-06 00:53:31 +04:00
|
|
|
#endif
|
2000-01-05 07:41:21 +03:00
|
|
|
|
|
|
|
int
|
2005-09-12 19:02:46 +04:00
|
|
|
rb_path_check(const char *path)
|
2000-01-05 07:41:21 +03:00
|
|
|
{
|
2006-09-07 18:28:36 +04:00
|
|
|
#if ENABLE_PATH_CHECK
|
2005-09-12 19:02:46 +04:00
|
|
|
const char *p0, *p, *pend;
|
2000-01-05 07:41:21 +03:00
|
|
|
const char sep = PATH_SEP_CHAR;
|
|
|
|
|
|
|
|
if (!path) return 1;
|
|
|
|
|
2001-11-08 09:43:14 +03:00
|
|
|
pend = path + strlen(path);
|
|
|
|
p0 = path;
|
|
|
|
p = strchr(path, sep);
|
|
|
|
if (!p) p = pend;
|
2001-07-16 08:22:46 +04:00
|
|
|
|
2000-01-05 07:41:21 +03:00
|
|
|
for (;;) {
|
2020-06-23 03:32:59 +03:00
|
|
|
if (!path_check_0(rb_str_new(p0, p - p0))) {
|
2001-11-08 09:43:14 +03:00
|
|
|
return 0; /* not safe */
|
|
|
|
}
|
|
|
|
p0 = p + 1;
|
2001-11-08 12:21:59 +03:00
|
|
|
if (p0 > pend) break;
|
2001-11-08 09:43:14 +03:00
|
|
|
p = strchr(p0, sep);
|
|
|
|
if (!p) p = pend;
|
2000-01-05 07:41:21 +03:00
|
|
|
}
|
2002-09-06 00:53:31 +04:00
|
|
|
#endif
|
2000-01-05 07:41:21 +03:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-10-18 00:09:10 +03:00
|
|
|
int
|
|
|
|
ruby_is_fd_loadable(int fd)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
return 1;
|
|
|
|
#else
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (fstat(fd, &st) < 0)
|
|
|
|
return 0;
|
2016-03-14 10:03:01 +03:00
|
|
|
|
2015-10-18 00:09:10 +03:00
|
|
|
if (S_ISREG(st.st_mode))
|
|
|
|
return 1;
|
2015-10-18 03:33:44 +03:00
|
|
|
|
2018-04-13 09:26:30 +03:00
|
|
|
if (S_ISFIFO(st.st_mode) || S_ISCHR(st.st_mode))
|
2016-03-14 10:03:01 +03:00
|
|
|
return -1;
|
2015-10-18 00:09:10 +03:00
|
|
|
|
2015-10-18 03:33:44 +03:00
|
|
|
if (S_ISDIR(st.st_mode))
|
|
|
|
errno = EISDIR;
|
|
|
|
else
|
|
|
|
errno = ENXIO;
|
|
|
|
|
2015-10-18 00:09:10 +03:00
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-02-28 19:51:25 +04:00
|
|
|
#ifndef _WIN32
|
|
|
|
int
|
Revert "reuse open(2) from rb_file_load_ok on POSIX-like system"
This reverts commit 35136e1e9c232ad7a03407b992b2e86b6df43f63.
test-spec has been failing since this revision.
.github/workflows/compilers.yml:82
https://github.com/ruby/ruby/actions/runs/4276884159/jobs/7445299562
```
env:
# Minimal flags to pass the check.
default_cc: 'gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes'
optflags: '-O2'
LDFLAGS: '-Wl,-z,now'
# FIXME: Drop skipping options
# https://bugs.ruby-lang.org/issues/18061
# https://sourceware.org/annobin/annobin.html/Test-pie.html
TEST_ANNOCHECK_OPTS: "--skip-pie --skip-gaps"
```
Failure:
```
1)
An exception occurred during: Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
2)
An exception occurred during: Kernel#require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel#require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
3)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
4)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
5)
An exception occurred during: Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
6)
An exception occurred during: Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
7)
An exception occurred during: Kernel.require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel.require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
8)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
9)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
10)
An exception occurred during: Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
11)
An exception occurred during: Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:197
Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
12)
An exception occurred during: Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:205
Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
13)
An exception occurred during: Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:399
Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
14)
An exception occurred during: Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:407
Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
```
2023-02-27 20:24:45 +03:00
|
|
|
rb_file_load_ok(const char *path)
|
2001-06-19 08:35:17 +04:00
|
|
|
{
|
2009-02-27 11:45:26 +03:00
|
|
|
int ret = 1;
|
2015-10-18 00:09:10 +03:00
|
|
|
/*
|
|
|
|
open(2) may block if path is FIFO and it's empty. Let's use O_NONBLOCK.
|
|
|
|
FIXME: Why O_NDELAY is checked?
|
|
|
|
*/
|
2015-10-16 09:54:38 +03:00
|
|
|
int mode = (O_RDONLY |
|
|
|
|
#if defined O_NONBLOCK
|
|
|
|
O_NONBLOCK |
|
|
|
|
#elif defined O_NDELAY
|
|
|
|
O_NDELAY |
|
|
|
|
#endif
|
|
|
|
0);
|
|
|
|
int fd = rb_cloexec_open(path, mode, 0);
|
2023-02-15 06:19:14 +03:00
|
|
|
if (fd < 0) {
|
|
|
|
if (!rb_gc_for_fd(errno)) return 0;
|
|
|
|
fd = rb_cloexec_open(path, mode, 0);
|
|
|
|
if (fd < 0) return 0;
|
|
|
|
}
|
2011-10-29 08:01:54 +04:00
|
|
|
rb_update_max_fd(fd);
|
2015-10-18 00:09:10 +03:00
|
|
|
ret = ruby_is_fd_loadable(fd);
|
Revert "reuse open(2) from rb_file_load_ok on POSIX-like system"
This reverts commit 35136e1e9c232ad7a03407b992b2e86b6df43f63.
test-spec has been failing since this revision.
.github/workflows/compilers.yml:82
https://github.com/ruby/ruby/actions/runs/4276884159/jobs/7445299562
```
env:
# Minimal flags to pass the check.
default_cc: 'gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes'
optflags: '-O2'
LDFLAGS: '-Wl,-z,now'
# FIXME: Drop skipping options
# https://bugs.ruby-lang.org/issues/18061
# https://sourceware.org/annobin/annobin.html/Test-pie.html
TEST_ANNOCHECK_OPTS: "--skip-pie --skip-gaps"
```
Failure:
```
1)
An exception occurred during: Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
2)
An exception occurred during: Kernel#require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel#require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
3)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
4)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
5)
An exception occurred during: Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
6)
An exception occurred during: Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
7)
An exception occurred during: Kernel.require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel.require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
8)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
9)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
10)
An exception occurred during: Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
11)
An exception occurred during: Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:197
Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
12)
An exception occurred during: Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:205
Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
13)
An exception occurred during: Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:399
Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
14)
An exception occurred during: Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:407
Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
```
2023-02-27 20:24:45 +03:00
|
|
|
(void)close(fd);
|
2009-02-27 11:45:26 +03:00
|
|
|
return ret;
|
2001-06-19 08:35:17 +04:00
|
|
|
}
|
Revert "reuse open(2) from rb_file_load_ok on POSIX-like system"
This reverts commit 35136e1e9c232ad7a03407b992b2e86b6df43f63.
test-spec has been failing since this revision.
.github/workflows/compilers.yml:82
https://github.com/ruby/ruby/actions/runs/4276884159/jobs/7445299562
```
env:
# Minimal flags to pass the check.
default_cc: 'gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes'
optflags: '-O2'
LDFLAGS: '-Wl,-z,now'
# FIXME: Drop skipping options
# https://bugs.ruby-lang.org/issues/18061
# https://sourceware.org/annobin/annobin.html/Test-pie.html
TEST_ANNOCHECK_OPTS: "--skip-pie --skip-gaps"
```
Failure:
```
1)
An exception occurred during: Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
2)
An exception occurred during: Kernel#require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel#require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
3)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
4)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
5)
An exception occurred during: Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
6)
An exception occurred during: Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
7)
An exception occurred during: Kernel.require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel.require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
8)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
9)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
10)
An exception occurred during: Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
11)
An exception occurred during: Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:197
Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
12)
An exception occurred during: Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:205
Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
13)
An exception occurred during: Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:399
Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
14)
An exception occurred during: Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:407
Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
```
2023-02-27 20:24:45 +03:00
|
|
|
#endif
|
2009-06-23 11:05:04 +04:00
|
|
|
|
2008-07-29 00:38:04 +04:00
|
|
|
static int
|
|
|
|
is_explicit_relative(const char *path)
|
|
|
|
{
|
|
|
|
if (*path++ != '.') return 0;
|
|
|
|
if (*path == '.') path++;
|
|
|
|
return isdirsep(*path);
|
|
|
|
}
|
|
|
|
|
2009-06-23 11:05:04 +04:00
|
|
|
static VALUE
|
|
|
|
copy_path_class(VALUE path, VALUE orig)
|
|
|
|
{
|
2021-09-29 14:01:14 +03:00
|
|
|
int encidx = rb_enc_get_index(orig);
|
2022-07-13 12:54:08 +03:00
|
|
|
if (encidx == ENCINDEX_ASCII_8BIT || encidx == ENCINDEX_US_ASCII)
|
2021-09-29 14:01:14 +03:00
|
|
|
encidx = rb_filesystem_encindex();
|
|
|
|
rb_enc_associate_index(path, encidx);
|
2014-06-12 08:09:41 +04:00
|
|
|
str_shrink(path);
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS(path, rb_obj_class(orig));
|
2009-06-23 11:05:04 +04:00
|
|
|
OBJ_FREEZE(path);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-09-21 05:06:22 +03:00
|
|
|
rb_find_file_ext(VALUE *filep, const char *const *ext)
|
2009-06-23 11:05:04 +04:00
|
|
|
{
|
|
|
|
const char *f = StringValueCStr(*filep);
|
|
|
|
VALUE fname = *filep, load_path, tmp;
|
2008-07-28 13:15:48 +04:00
|
|
|
long i, j, fnlen;
|
2009-06-23 11:05:04 +04:00
|
|
|
int expanded = 0;
|
2008-07-28 13:15:48 +04:00
|
|
|
|
|
|
|
if (!ext[0]) return 0;
|
2001-06-19 08:35:17 +04:00
|
|
|
|
2001-07-14 19:17:19 +04:00
|
|
|
if (f[0] == '~') {
|
2010-03-02 08:29:27 +03:00
|
|
|
fname = file_expand_path_1(fname);
|
2009-06-23 11:05:04 +04:00
|
|
|
f = RSTRING_PTR(fname);
|
2001-07-26 07:54:48 +04:00
|
|
|
*filep = fname;
|
2009-06-23 11:05:04 +04:00
|
|
|
expanded = 1;
|
2001-06-19 08:35:17 +04:00
|
|
|
}
|
|
|
|
|
2010-03-13 04:34:38 +03:00
|
|
|
if (expanded || rb_is_absolute_path(f) || is_explicit_relative(f)) {
|
2010-03-02 08:29:27 +03:00
|
|
|
if (!expanded) fname = file_expand_path_1(fname);
|
2008-07-29 00:38:04 +04:00
|
|
|
fnlen = RSTRING_LEN(fname);
|
2001-06-19 08:35:17 +04:00
|
|
|
for (i=0; ext[i]; i++) {
|
2001-07-14 19:17:19 +04:00
|
|
|
rb_str_cat2(fname, ext[i]);
|
Revert "reuse open(2) from rb_file_load_ok on POSIX-like system"
This reverts commit 35136e1e9c232ad7a03407b992b2e86b6df43f63.
test-spec has been failing since this revision.
.github/workflows/compilers.yml:82
https://github.com/ruby/ruby/actions/runs/4276884159/jobs/7445299562
```
env:
# Minimal flags to pass the check.
default_cc: 'gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes'
optflags: '-O2'
LDFLAGS: '-Wl,-z,now'
# FIXME: Drop skipping options
# https://bugs.ruby-lang.org/issues/18061
# https://sourceware.org/annobin/annobin.html/Test-pie.html
TEST_ANNOCHECK_OPTS: "--skip-pie --skip-gaps"
```
Failure:
```
1)
An exception occurred during: Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
2)
An exception occurred during: Kernel#require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel#require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
3)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
4)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
5)
An exception occurred during: Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
6)
An exception occurred during: Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
7)
An exception occurred during: Kernel.require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel.require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
8)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
9)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
10)
An exception occurred during: Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
11)
An exception occurred during: Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:197
Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
12)
An exception occurred during: Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:205
Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
13)
An exception occurred during: Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:399
Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
14)
An exception occurred during: Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:407
Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
```
2023-02-27 20:24:45 +03:00
|
|
|
if (rb_file_load_ok(RSTRING_PTR(fname))) {
|
2009-06-23 11:05:04 +04:00
|
|
|
*filep = copy_path_class(fname, *filep);
|
2009-04-06 11:38:52 +04:00
|
|
|
return (int)(i+1);
|
2001-07-14 19:17:19 +04:00
|
|
|
}
|
2008-07-29 00:38:04 +04:00
|
|
|
rb_str_set_len(fname, fnlen);
|
2001-06-19 08:35:17 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-11-05 19:27:08 +04:00
|
|
|
RB_GC_GUARD(load_path) = rb_get_expanded_load_path();
|
2008-04-30 13:03:03 +04:00
|
|
|
if (!load_path) return 0;
|
2001-06-19 08:35:17 +04:00
|
|
|
|
2008-07-28 13:15:48 +04:00
|
|
|
fname = rb_str_dup(*filep);
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_CLEAR_CLASS(fname);
|
2008-07-28 13:15:48 +04:00
|
|
|
fnlen = RSTRING_LEN(fname);
|
|
|
|
tmp = rb_str_tmp_new(MAXPATHLEN + 2);
|
2012-08-23 11:46:12 +04:00
|
|
|
rb_enc_associate_index(tmp, rb_usascii_encindex());
|
2007-11-19 10:10:09 +03:00
|
|
|
for (j=0; ext[j]; j++) {
|
|
|
|
rb_str_cat2(fname, ext[j]);
|
2008-04-30 13:03:03 +04:00
|
|
|
for (i = 0; i < RARRAY_LEN(load_path); i++) {
|
2013-05-13 13:56:22 +04:00
|
|
|
VALUE str = RARRAY_AREF(load_path, i);
|
2001-06-19 08:35:17 +04:00
|
|
|
|
2019-09-21 05:06:22 +03:00
|
|
|
RB_GC_GUARD(str) = rb_get_path(str);
|
2007-11-19 10:10:09 +03:00
|
|
|
if (RSTRING_LEN(str) == 0) continue;
|
2012-08-24 07:44:56 +04:00
|
|
|
rb_file_expand_path_internal(fname, str, 0, 0, tmp);
|
Revert "reuse open(2) from rb_file_load_ok on POSIX-like system"
This reverts commit 35136e1e9c232ad7a03407b992b2e86b6df43f63.
test-spec has been failing since this revision.
.github/workflows/compilers.yml:82
https://github.com/ruby/ruby/actions/runs/4276884159/jobs/7445299562
```
env:
# Minimal flags to pass the check.
default_cc: 'gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes'
optflags: '-O2'
LDFLAGS: '-Wl,-z,now'
# FIXME: Drop skipping options
# https://bugs.ruby-lang.org/issues/18061
# https://sourceware.org/annobin/annobin.html/Test-pie.html
TEST_ANNOCHECK_OPTS: "--skip-pie --skip-gaps"
```
Failure:
```
1)
An exception occurred during: Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
2)
An exception occurred during: Kernel#require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel#require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
3)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
4)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
5)
An exception occurred during: Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
6)
An exception occurred during: Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
7)
An exception occurred during: Kernel.require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel.require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
8)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
9)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
10)
An exception occurred during: Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
11)
An exception occurred during: Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:197
Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
12)
An exception occurred during: Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:205
Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
13)
An exception occurred during: Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:399
Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
14)
An exception occurred during: Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:407
Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
```
2023-02-27 20:24:45 +03:00
|
|
|
if (rb_file_load_ok(RSTRING_PTR(tmp))) {
|
2009-06-23 11:05:04 +04:00
|
|
|
*filep = copy_path_class(tmp, *filep);
|
2009-04-06 11:38:52 +04:00
|
|
|
return (int)(j+1);
|
2001-07-14 19:17:19 +04:00
|
|
|
}
|
2001-06-19 08:35:17 +04:00
|
|
|
}
|
2008-07-28 13:15:48 +04:00
|
|
|
rb_str_set_len(fname, fnlen);
|
2001-06-19 08:35:17 +04:00
|
|
|
}
|
2014-09-21 07:26:47 +04:00
|
|
|
rb_str_resize(tmp, 0);
|
2008-05-08 11:46:30 +04:00
|
|
|
RB_GC_GUARD(load_path);
|
2001-06-19 08:35:17 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-07-14 19:17:19 +04:00
|
|
|
VALUE
|
2019-09-21 05:06:22 +03:00
|
|
|
rb_find_file(VALUE path)
|
2000-01-05 07:41:21 +03:00
|
|
|
{
|
2008-04-30 13:03:03 +04:00
|
|
|
VALUE tmp, load_path;
|
2008-06-01 23:55:25 +04:00
|
|
|
const char *f = StringValueCStr(path);
|
2009-06-23 11:05:04 +04:00
|
|
|
int expanded = 0;
|
2000-01-05 07:41:21 +03:00
|
|
|
|
2001-07-14 19:17:19 +04:00
|
|
|
if (f[0] == '~') {
|
2010-03-02 08:29:27 +03:00
|
|
|
tmp = file_expand_path_1(path);
|
2009-06-23 11:05:04 +04:00
|
|
|
path = copy_path_class(tmp, path);
|
|
|
|
f = RSTRING_PTR(path);
|
|
|
|
expanded = 1;
|
2001-06-19 08:35:17 +04:00
|
|
|
}
|
|
|
|
|
2010-03-13 04:34:38 +03:00
|
|
|
if (expanded || rb_is_absolute_path(f) || is_explicit_relative(f)) {
|
Revert "reuse open(2) from rb_file_load_ok on POSIX-like system"
This reverts commit 35136e1e9c232ad7a03407b992b2e86b6df43f63.
test-spec has been failing since this revision.
.github/workflows/compilers.yml:82
https://github.com/ruby/ruby/actions/runs/4276884159/jobs/7445299562
```
env:
# Minimal flags to pass the check.
default_cc: 'gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes'
optflags: '-O2'
LDFLAGS: '-Wl,-z,now'
# FIXME: Drop skipping options
# https://bugs.ruby-lang.org/issues/18061
# https://sourceware.org/annobin/annobin.html/Test-pie.html
TEST_ANNOCHECK_OPTS: "--skip-pie --skip-gaps"
```
Failure:
```
1)
An exception occurred during: Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
2)
An exception occurred during: Kernel#require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel#require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
3)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
4)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
5)
An exception occurred during: Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
6)
An exception occurred during: Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
7)
An exception occurred during: Kernel.require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel.require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
8)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
9)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
10)
An exception occurred during: Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
11)
An exception occurred during: Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:197
Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
12)
An exception occurred during: Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:205
Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
13)
An exception occurred during: Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:399
Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
14)
An exception occurred during: Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:407
Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
```
2023-02-27 20:24:45 +03:00
|
|
|
if (!rb_file_load_ok(f)) return 0;
|
2009-06-23 11:05:04 +04:00
|
|
|
if (!expanded)
|
2010-03-02 08:29:27 +03:00
|
|
|
path = copy_path_class(file_expand_path_1(path), path);
|
2008-07-29 00:38:04 +04:00
|
|
|
return path;
|
2000-01-05 07:41:21 +03:00
|
|
|
}
|
|
|
|
|
2012-11-05 19:27:08 +04:00
|
|
|
RB_GC_GUARD(load_path) = rb_get_expanded_load_path();
|
2008-04-30 13:03:03 +04:00
|
|
|
if (load_path) {
|
2002-08-21 19:47:54 +04:00
|
|
|
long i;
|
2000-01-05 07:41:21 +03:00
|
|
|
|
2008-07-28 13:15:48 +04:00
|
|
|
tmp = rb_str_tmp_new(MAXPATHLEN + 2);
|
2012-08-23 11:46:12 +04:00
|
|
|
rb_enc_associate_index(tmp, rb_usascii_encindex());
|
2008-04-30 13:03:03 +04:00
|
|
|
for (i = 0; i < RARRAY_LEN(load_path); i++) {
|
2013-05-13 13:56:22 +04:00
|
|
|
VALUE str = RARRAY_AREF(load_path, i);
|
2019-09-21 05:06:22 +03:00
|
|
|
RB_GC_GUARD(str) = rb_get_path(str);
|
2006-08-31 14:47:44 +04:00
|
|
|
if (RSTRING_LEN(str) > 0) {
|
2012-08-24 07:44:56 +04:00
|
|
|
rb_file_expand_path_internal(path, str, 0, 0, tmp);
|
2008-07-28 13:15:48 +04:00
|
|
|
f = RSTRING_PTR(tmp);
|
Revert "reuse open(2) from rb_file_load_ok on POSIX-like system"
This reverts commit 35136e1e9c232ad7a03407b992b2e86b6df43f63.
test-spec has been failing since this revision.
.github/workflows/compilers.yml:82
https://github.com/ruby/ruby/actions/runs/4276884159/jobs/7445299562
```
env:
# Minimal flags to pass the check.
default_cc: 'gcc-11 -fcf-protection -Wa,--generate-missing-build-notes=yes'
optflags: '-O2'
LDFLAGS: '-Wl,-z,now'
# FIXME: Drop skipping options
# https://bugs.ruby-lang.org/issues/18061
# https://sourceware.org/annobin/annobin.html/Test-pie.html
TEST_ANNOCHECK_OPTS: "--skip-pie --skip-gaps"
```
Failure:
```
1)
An exception occurred during: Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel#require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
2)
An exception occurred during: Kernel#require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel#require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
3)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel#require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
4)
An exception occurred during: Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel#require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
5)
An exception occurred during: Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel#require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:5:in `<top (required)>'
6)
An exception occurred during: Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:317
Kernel.require (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
7)
An exception occurred during: Kernel.require ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:330
Kernel.require ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
8)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:535
Kernel.require ($LOADED_FEATURES) does not load a non-canonical path for a file already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
9)
An exception occurred during: Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:551
Kernel.require ($LOADED_FEATURES) does not load a ../ relative path for a file already loaded ERROR
LeakError: Leaked file descriptor: 9 : #<File:../code/load_fixture.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
10)
An exception occurred during: Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required
/__w/ruby/ruby/src/spec/ruby/core/kernel/shared/require.rb:563
Kernel.require ($LOADED_FEATURES) complex, enumerator, rational, thread, ruby2_keywords are already required ERROR
LeakError: Closed file descriptor: 8
Closed file descriptor: 9
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_spec.rb:23:in `<top (required)>'
11)
An exception occurred during: Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:197
Kernel#require_relative with a relative path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
12)
An exception occurred during: Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:205
Kernel#require_relative with a relative path ($LOADED_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:4:in `<top (required)>'
13)
An exception occurred during: Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:399
Kernel#require_relative with an absolute path (file extensions) does not load a C-extension file if a complex-extensioned .rb file is already loaded ERROR
LeakError: Leaked file descriptor: 8 : #<File:/__w/ruby/ruby/src/spec/ruby/fixtures/code/load_fixture.ext.rb>
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
14)
An exception occurred during: Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:407
Kernel#require_relative with an absolute path ($LOAD_FEATURES) stores an absolute path ERROR
LeakError: Closed file descriptor: 8
/__w/ruby/ruby/src/spec/ruby/core/kernel/require_relative_spec.rb:277:in `<top (required)>'
```
2023-02-27 20:24:45 +03:00
|
|
|
if (rb_file_load_ok(f)) goto found;
|
2000-01-05 07:41:21 +03:00
|
|
|
}
|
|
|
|
}
|
2014-09-21 07:26:47 +04:00
|
|
|
rb_str_resize(tmp, 0);
|
2008-07-28 13:15:48 +04:00
|
|
|
return 0;
|
2000-01-05 07:41:21 +03:00
|
|
|
}
|
|
|
|
else {
|
2002-08-27 12:31:08 +04:00
|
|
|
return 0; /* no path, no load */
|
|
|
|
}
|
2008-07-28 13:15:48 +04:00
|
|
|
|
2009-06-23 11:05:04 +04:00
|
|
|
found:
|
|
|
|
return copy_path_class(tmp, path);
|
2000-01-05 07:41:21 +03:00
|
|
|
}
|
|
|
|
|
2022-09-14 05:32:24 +03:00
|
|
|
#define define_filetest_function(name, func, argc) do { \
|
|
|
|
rb_define_module_function(rb_mFileTest, name, func, argc); \
|
|
|
|
rb_define_singleton_method(rb_cFile, name, func, argc); \
|
|
|
|
} while(false)
|
2000-09-18 12:47:10 +04:00
|
|
|
|
2018-02-07 02:40:19 +03:00
|
|
|
const char ruby_null_device[] =
|
2010-08-27 10:26:41 +04:00
|
|
|
#if defined DOSISH
|
|
|
|
"NUL"
|
|
|
|
#elif defined AMIGA || defined __amigaos__
|
|
|
|
"NIL"
|
|
|
|
#elif defined __VMS
|
|
|
|
"NL:"
|
|
|
|
#else
|
|
|
|
"/dev/null"
|
|
|
|
#endif
|
|
|
|
;
|
2003-12-21 10:28:54 +03:00
|
|
|
|
|
|
|
/*
|
2022-01-14 03:00:24 +03:00
|
|
|
* A \File object is a representation of a file in the underlying platform.
|
|
|
|
*
|
|
|
|
* \Class \File extends module FileTest, supporting such singleton methods
|
|
|
|
* as <tt>File.exist?</tt>.
|
|
|
|
*
|
2023-09-25 00:57:21 +03:00
|
|
|
* == About the Examples
|
2022-09-22 00:34:55 +03:00
|
|
|
*
|
|
|
|
* Many examples here use these variables:
|
|
|
|
*
|
|
|
|
* :include: doc/examples/files.rdoc
|
|
|
|
*
|
2022-10-02 16:24:08 +03:00
|
|
|
* == Access Modes
|
2022-09-22 00:34:55 +03:00
|
|
|
*
|
2023-08-12 19:44:38 +03:00
|
|
|
* Methods File.new and File.open each create a \File object for a given file path.
|
2022-09-22 00:34:55 +03:00
|
|
|
*
|
|
|
|
* === \String Access Modes
|
|
|
|
*
|
2023-08-12 19:44:38 +03:00
|
|
|
* Methods File.new and File.open each may take string argument +mode+, which:
|
2022-09-22 00:34:55 +03:00
|
|
|
*
|
|
|
|
* - Begins with a 1- or 2-character
|
|
|
|
* {read/write mode}[rdoc-ref:File@Read-2FWrite+Mode].
|
|
|
|
* - May also contain a 1-character {data mode}[rdoc-ref:File@Data+Mode].
|
|
|
|
* - May also contain a 1-character
|
|
|
|
* {file-create mode}[rdoc-ref:File@File-Create+Mode].
|
|
|
|
*
|
|
|
|
* ==== Read/Write Mode
|
|
|
|
*
|
|
|
|
* The read/write +mode+ determines:
|
|
|
|
*
|
|
|
|
* - Whether the file is to be initially truncated.
|
|
|
|
*
|
|
|
|
* - Whether reading is allowed, and if so:
|
|
|
|
*
|
|
|
|
* - The initial read position in the file.
|
|
|
|
* - Where in the file reading can occur.
|
|
|
|
*
|
|
|
|
* - Whether writing is allowed, and if so:
|
|
|
|
*
|
|
|
|
* - The initial write position in the file.
|
|
|
|
* - Where in the file writing can occur.
|
|
|
|
*
|
|
|
|
* These tables summarize:
|
|
|
|
*
|
|
|
|
* Read/Write Modes for Existing File
|
|
|
|
*
|
|
|
|
* |------|-----------|----------|----------|----------|-----------|
|
|
|
|
* | R/W | Initial | | Initial | | Initial |
|
|
|
|
* | Mode | Truncate? | Read | Read Pos | Write | Write Pos |
|
|
|
|
* |------|-----------|----------|----------|----------|-----------|
|
|
|
|
* | 'r' | No | Anywhere | 0 | Error | - |
|
|
|
|
* | 'w' | Yes | Error | - | Anywhere | 0 |
|
|
|
|
* | 'a' | No | Error | - | End only | End |
|
|
|
|
* | 'r+' | No | Anywhere | 0 | Anywhere | 0 |
|
|
|
|
* | 'w+' | Yes | Anywhere | 0 | Anywhere | 0 |
|
|
|
|
* | 'a+' | No | Anywhere | End | End only | End |
|
|
|
|
* |------|-----------|----------|----------|----------|-----------|
|
|
|
|
*
|
|
|
|
* Read/Write Modes for \File To Be Created
|
|
|
|
*
|
|
|
|
* |------|----------|----------|----------|-----------|
|
|
|
|
* | R/W | | Initial | | Initial |
|
|
|
|
* | Mode | Read | Read Pos | Write | Write Pos |
|
|
|
|
* |------|----------|----------|----------|-----------|
|
|
|
|
* | 'w' | Error | - | Anywhere | 0 |
|
|
|
|
* | 'a' | Error | - | End only | 0 |
|
|
|
|
* | 'w+' | Anywhere | 0 | Anywhere | 0 |
|
|
|
|
* | 'a+' | Anywhere | 0 | End only | End |
|
|
|
|
* |------|----------|----------|----------|-----------|
|
|
|
|
*
|
|
|
|
* Note that modes <tt>'r'</tt> and <tt>'r+'</tt> are not allowed
|
|
|
|
* for a non-existent file (exception raised).
|
|
|
|
*
|
|
|
|
* In the tables:
|
|
|
|
*
|
|
|
|
* - +Anywhere+ means that methods IO#rewind, IO#pos=, and IO#seek
|
|
|
|
* may be used to change the file's position,
|
|
|
|
* so that allowed reading or writing may occur anywhere in the file.
|
|
|
|
* - <tt>End only</tt> means that writing can occur only at end-of-file,
|
|
|
|
* and that methods IO#rewind, IO#pos=, and IO#seek do not affect writing.
|
|
|
|
* - +Error+ means that an exception is raised if disallowed reading or writing
|
|
|
|
* is attempted.
|
|
|
|
*
|
|
|
|
* ===== Read/Write Modes for Existing \File
|
|
|
|
*
|
|
|
|
* - <tt>'r'</tt>:
|
|
|
|
*
|
|
|
|
* - File is not initially truncated:
|
|
|
|
*
|
|
|
|
* f = File.new('t.txt') # => #<File:t.txt>
|
|
|
|
* f.size == 0 # => false
|
|
|
|
*
|
|
|
|
* - File's initial read position is 0:
|
|
|
|
*
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - File may be read anywhere; see IO#rewind, IO#pos=, IO#seek:
|
|
|
|
*
|
|
|
|
* f.readline # => "First line\n"
|
|
|
|
* f.readline # => "Second line\n"
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.readline # => "First line\n"
|
|
|
|
*
|
|
|
|
* f.pos = 1
|
|
|
|
* f.readline # => "irst line\n"
|
|
|
|
*
|
|
|
|
* f.seek(1, :CUR)
|
|
|
|
* f.readline # => "econd line\n"
|
|
|
|
*
|
|
|
|
* - Writing is not allowed:
|
|
|
|
*
|
|
|
|
* f.write('foo') # Raises IOError.
|
|
|
|
*
|
|
|
|
* - <tt>'w'</tt>:
|
|
|
|
*
|
|
|
|
* - File is initially truncated:
|
|
|
|
*
|
|
|
|
* path = 't.tmp'
|
|
|
|
* File.write(path, text)
|
|
|
|
* f = File.new(path, 'w')
|
|
|
|
* f.size == 0 # => true
|
|
|
|
*
|
|
|
|
* - File's initial write position is 0:
|
|
|
|
*
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - File may be written anywhere (even past end-of-file);
|
|
|
|
* see IO#rewind, IO#pos=, IO#seek:
|
|
|
|
*
|
|
|
|
* f.write('foo')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foo"
|
|
|
|
* f.pos # => 3
|
|
|
|
*
|
|
|
|
* f.write('bar')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobar"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.write('baz')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbar"
|
|
|
|
* f.pos # => 3
|
|
|
|
*
|
|
|
|
* f.pos = 3
|
|
|
|
* f.write('foo')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazfoo"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.seek(-3, :END)
|
|
|
|
* f.write('bam')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbam"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.pos = 8
|
|
|
|
* f.write('bah') # Zero padding as needed.
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbam\u0000\u0000bah"
|
|
|
|
* f.pos # => 11
|
|
|
|
*
|
|
|
|
* - Reading is not allowed:
|
|
|
|
*
|
|
|
|
* f.read # Raises IOError.
|
|
|
|
*
|
|
|
|
* - <tt>'a'</tt>:
|
|
|
|
*
|
|
|
|
* - File is not initially truncated:
|
|
|
|
*
|
|
|
|
* path = 't.tmp'
|
|
|
|
* File.write(path, 'foo')
|
|
|
|
* f = File.new(path, 'a')
|
|
|
|
* f.size == 0 # => false
|
|
|
|
*
|
|
|
|
* - File's initial position is 0 (but is ignored):
|
|
|
|
*
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - File may be written only at end-of-file;
|
|
|
|
* IO#rewind, IO#pos=, IO#seek do not affect writing:
|
|
|
|
*
|
|
|
|
* f.write('bar')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobar"
|
|
|
|
* f.write('baz')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobarbaz"
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.write('bat')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobarbazbat"
|
|
|
|
*
|
|
|
|
* - Reading is not allowed:
|
|
|
|
*
|
|
|
|
* f.read # Raises IOError.
|
|
|
|
*
|
|
|
|
* - <tt>'r+'</tt>:
|
|
|
|
*
|
|
|
|
* - File is not initially truncated:
|
|
|
|
*
|
|
|
|
* path = 't.tmp'
|
|
|
|
* File.write(path, text)
|
|
|
|
* f = File.new(path, 'r+')
|
|
|
|
* f.size == 0 # => false
|
|
|
|
*
|
|
|
|
* - File's initial read position is 0:
|
|
|
|
*
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - File may be read or written anywhere (even past end-of-file);
|
|
|
|
* see IO#rewind, IO#pos=, IO#seek:
|
|
|
|
*
|
|
|
|
* f.readline # => "First line\n"
|
|
|
|
* f.readline # => "Second line\n"
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.readline # => "First line\n"
|
|
|
|
*
|
|
|
|
* f.pos = 1
|
|
|
|
* f.readline # => "irst line\n"
|
|
|
|
*
|
|
|
|
* f.seek(1, :CUR)
|
|
|
|
* f.readline # => "econd line\n"
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.write('WWW')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path)
|
|
|
|
* # => "WWWst line\nSecond line\nFourth line\nFifth line\n"
|
|
|
|
*
|
|
|
|
* f.pos = 10
|
|
|
|
* f.write('XXX')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path)
|
|
|
|
* # => "WWWst lineXXXecond line\nFourth line\nFifth line\n"
|
|
|
|
*
|
|
|
|
* f.seek(-6, :END)
|
|
|
|
* # => 0
|
|
|
|
* f.write('YYY')
|
|
|
|
* # => 3
|
|
|
|
* f.flush
|
|
|
|
* # => #<File:t.tmp>
|
|
|
|
* File.read(path)
|
|
|
|
* # => "WWWst lineXXXecond line\nFourth line\nFifth YYYe\n"
|
|
|
|
*
|
|
|
|
* f.seek(2, :END)
|
|
|
|
* f.write('ZZZ') # Zero padding as needed.
|
|
|
|
* f.flush
|
|
|
|
* File.read(path)
|
|
|
|
* # => "WWWst lineXXXecond line\nFourth line\nFifth YYYe\n\u0000\u0000ZZZ"
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* - <tt>'a+'</tt>:
|
|
|
|
*
|
|
|
|
* - File is not initially truncated:
|
|
|
|
*
|
|
|
|
* path = 't.tmp'
|
|
|
|
* File.write(path, 'foo')
|
|
|
|
* f = File.new(path, 'a+')
|
|
|
|
* f.size == 0 # => false
|
|
|
|
*
|
|
|
|
* - File's initial read position is 0:
|
|
|
|
*
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - File may be written only at end-of-file;
|
|
|
|
* IO#rewind, IO#pos=, IO#seek do not affect writing:
|
|
|
|
*
|
|
|
|
* f.write('bar')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobar"
|
|
|
|
* f.write('baz')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobarbaz"
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.write('bat')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobarbazbat"
|
|
|
|
*
|
|
|
|
* - File may be read anywhere; see IO#rewind, IO#pos=, IO#seek:
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.read # => "foobarbazbat"
|
|
|
|
*
|
|
|
|
* f.pos = 3
|
|
|
|
* f.read # => "barbazbat"
|
|
|
|
*
|
|
|
|
* f.seek(-3, :END)
|
|
|
|
* f.read # => "bat"
|
|
|
|
*
|
|
|
|
* ===== Read/Write Modes for \File To Be Created
|
|
|
|
*
|
|
|
|
* Note that modes <tt>'r'</tt> and <tt>'r+'</tt> are not allowed
|
|
|
|
* for a non-existent file (exception raised).
|
|
|
|
*
|
|
|
|
* - <tt>'w'</tt>:
|
|
|
|
*
|
|
|
|
* - File's initial write position is 0:
|
|
|
|
*
|
|
|
|
* path = 't.tmp'
|
|
|
|
* FileUtils.rm_f(path)
|
|
|
|
* f = File.new(path, 'w')
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - File may be written anywhere (even past end-of-file);
|
|
|
|
* see IO#rewind, IO#pos=, IO#seek:
|
|
|
|
*
|
|
|
|
* f.write('foo')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foo"
|
|
|
|
* f.pos # => 3
|
|
|
|
*
|
|
|
|
* f.write('bar')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobar"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.write('baz')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbar"
|
|
|
|
* f.pos # => 3
|
|
|
|
*
|
|
|
|
* f.pos = 3
|
|
|
|
* f.write('foo')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazfoo"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.seek(-3, :END)
|
|
|
|
* f.write('bam')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbam"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.pos = 8
|
|
|
|
* f.write('bah') # Zero padding as needed.
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbam\u0000\u0000bah"
|
|
|
|
* f.pos # => 11
|
|
|
|
*
|
|
|
|
* - Reading is not allowed:
|
|
|
|
*
|
|
|
|
* f.read # Raises IOError.
|
|
|
|
*
|
|
|
|
* - <tt>'a'</tt>:
|
|
|
|
*
|
|
|
|
* - File's initial write position is 0:
|
|
|
|
*
|
|
|
|
* path = 't.tmp'
|
|
|
|
* FileUtils.rm_f(path)
|
|
|
|
* f = File.new(path, 'a')
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - Writing occurs only at end-of-file:
|
|
|
|
*
|
|
|
|
* f.write('foo')
|
|
|
|
* f.pos # => 3
|
|
|
|
* f.write('bar')
|
|
|
|
* f.pos # => 6
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobar"
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.write('baz')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobarbaz"
|
|
|
|
*
|
|
|
|
* - Reading is not allowed:
|
|
|
|
*
|
|
|
|
* f.read # Raises IOError.
|
|
|
|
*
|
|
|
|
* - <tt>'w+'</tt>:
|
|
|
|
*
|
|
|
|
* - File's initial position is 0:
|
|
|
|
*
|
|
|
|
* path = 't.tmp'
|
|
|
|
* FileUtils.rm_f(path)
|
|
|
|
* f = File.new(path, 'w+')
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - File may be written anywhere (even past end-of-file);
|
|
|
|
* see IO#rewind, IO#pos=, IO#seek:
|
|
|
|
*
|
|
|
|
* f.write('foo')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foo"
|
|
|
|
* f.pos # => 3
|
|
|
|
*
|
|
|
|
* f.write('bar')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobar"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.write('baz')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbar"
|
|
|
|
* f.pos # => 3
|
|
|
|
*
|
|
|
|
* f.pos = 3
|
|
|
|
* f.write('foo')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazfoo"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.seek(-3, :END)
|
|
|
|
* f.write('bam')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbam"
|
|
|
|
* f.pos # => 6
|
|
|
|
*
|
|
|
|
* f.pos = 8
|
|
|
|
* f.write('bah') # Zero padding as needed.
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "bazbam\u0000\u0000bah"
|
|
|
|
* f.pos # => 11
|
|
|
|
*
|
|
|
|
* - File may be read anywhere (even past end-of-file);
|
|
|
|
* see IO#rewind, IO#pos=, IO#seek:
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* # => 0
|
|
|
|
* f.read
|
|
|
|
* # => "bazbam\u0000\u0000bah"
|
|
|
|
*
|
|
|
|
* f.pos = 3
|
|
|
|
* # => 3
|
|
|
|
* f.read
|
|
|
|
* # => "bam\u0000\u0000bah"
|
|
|
|
*
|
|
|
|
* f.seek(-3, :END)
|
|
|
|
* # => 0
|
|
|
|
* f.read
|
|
|
|
* # => "bah"
|
|
|
|
*
|
|
|
|
* - <tt>'a+'</tt>:
|
|
|
|
*
|
|
|
|
* - File's initial write position is 0:
|
|
|
|
*
|
|
|
|
* path = 't.tmp'
|
|
|
|
* FileUtils.rm_f(path)
|
|
|
|
* f = File.new(path, 'a+')
|
|
|
|
* f.pos # => 0
|
|
|
|
*
|
|
|
|
* - Writing occurs only at end-of-file:
|
|
|
|
*
|
|
|
|
* f.write('foo')
|
|
|
|
* f.pos # => 3
|
|
|
|
* f.write('bar')
|
|
|
|
* f.pos # => 6
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobar"
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.write('baz')
|
|
|
|
* f.flush
|
|
|
|
* File.read(path) # => "foobarbaz"
|
|
|
|
*
|
|
|
|
* - File may be read anywhere (even past end-of-file);
|
|
|
|
* see IO#rewind, IO#pos=, IO#seek:
|
|
|
|
*
|
|
|
|
* f.rewind
|
|
|
|
* f.read # => "foobarbaz"
|
|
|
|
*
|
|
|
|
* f.pos = 3
|
|
|
|
* f.read # => "barbaz"
|
|
|
|
*
|
|
|
|
* f.seek(-3, :END)
|
|
|
|
* f.read # => "baz"
|
|
|
|
*
|
|
|
|
* f.pos = 800
|
|
|
|
* f.read # => ""
|
|
|
|
*
|
2022-10-19 18:34:51 +03:00
|
|
|
* ==== \Data Mode
|
2022-09-22 00:34:55 +03:00
|
|
|
*
|
|
|
|
* To specify whether data is to be treated as text or as binary data,
|
|
|
|
* either of the following may be suffixed to any of the string read/write modes
|
|
|
|
* above:
|
|
|
|
*
|
|
|
|
* - <tt>'t'</tt>: Text data; sets the default external encoding
|
|
|
|
* to <tt>Encoding::UTF_8</tt>;
|
|
|
|
* on Windows, enables conversion between EOL and CRLF
|
|
|
|
* and enables interpreting <tt>0x1A</tt> as an end-of-file marker.
|
|
|
|
* - <tt>'b'</tt>: Binary data; sets the default external encoding
|
|
|
|
* to <tt>Encoding::ASCII_8BIT</tt>;
|
|
|
|
* on Windows, suppresses conversion between EOL and CRLF
|
|
|
|
* and disables interpreting <tt>0x1A</tt> as an end-of-file marker.
|
|
|
|
*
|
|
|
|
* If neither is given, the stream defaults to text data.
|
|
|
|
*
|
|
|
|
* Examples:
|
|
|
|
*
|
|
|
|
* File.new('t.txt', 'rt')
|
|
|
|
* File.new('t.dat', 'rb')
|
|
|
|
*
|
|
|
|
* When the data mode is specified, the read/write mode may not be omitted,
|
|
|
|
* and the data mode must precede the file-create mode, if given:
|
|
|
|
*
|
|
|
|
* File.new('t.dat', 'b') # Raises an exception.
|
|
|
|
* File.new('t.dat', 'rxb') # Raises an exception.
|
|
|
|
*
|
|
|
|
* ==== \File-Create Mode
|
|
|
|
*
|
|
|
|
* The following may be suffixed to any writable string mode above:
|
|
|
|
*
|
|
|
|
* - <tt>'x'</tt>: Creates the file if it does not exist;
|
|
|
|
* raises an exception if the file exists.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
*
|
|
|
|
* File.new('t.tmp', 'wx')
|
|
|
|
*
|
|
|
|
* When the file-create mode is specified, the read/write mode may not be omitted,
|
|
|
|
* and the file-create mode must follow the data mode:
|
|
|
|
*
|
|
|
|
* File.new('t.dat', 'x') # Raises an exception.
|
|
|
|
* File.new('t.dat', 'rxb') # Raises an exception.
|
|
|
|
*
|
|
|
|
* === \Integer Access Modes
|
|
|
|
*
|
|
|
|
* When mode is an integer it must be one or more of the following constants,
|
|
|
|
* which may be combined by the bitwise OR operator <tt>|</tt>:
|
|
|
|
*
|
|
|
|
* - +File::RDONLY+: Open for reading only.
|
|
|
|
* - +File::WRONLY+: Open for writing only.
|
|
|
|
* - +File::RDWR+: Open for reading and writing.
|
|
|
|
* - +File::APPEND+: Open for appending only.
|
|
|
|
*
|
|
|
|
* Examples:
|
|
|
|
*
|
|
|
|
* File.new('t.txt', File::RDONLY)
|
|
|
|
* File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)
|
|
|
|
*
|
|
|
|
* Note: Method IO#set_encoding does not allow the mode to be specified as an integer.
|
|
|
|
*
|
|
|
|
* === File-Create Mode Specified as an \Integer
|
|
|
|
*
|
|
|
|
* These constants may also be ORed into the integer mode:
|
|
|
|
*
|
|
|
|
* - +File::CREAT+: Create file if it does not exist.
|
|
|
|
* - +File::EXCL+: Raise an exception if +File::CREAT+ is given and the file exists.
|
|
|
|
*
|
2022-10-19 18:34:51 +03:00
|
|
|
* === \Data Mode Specified as an \Integer
|
2022-09-22 00:34:55 +03:00
|
|
|
*
|
2022-12-10 05:56:02 +03:00
|
|
|
* \Data mode cannot be specified as an integer.
|
2022-09-22 00:34:55 +03:00
|
|
|
* When the stream access mode is given as an integer,
|
|
|
|
* the data mode is always text, never binary.
|
|
|
|
*
|
|
|
|
* Note that although there is a constant +File::BINARY+,
|
|
|
|
* setting its value in an integer stream mode has no effect;
|
|
|
|
* this is because, as documented in File::Constants,
|
|
|
|
* the +File::BINARY+ value disables line code conversion,
|
|
|
|
* but does not change the external encoding.
|
|
|
|
*
|
|
|
|
* === Encodings
|
|
|
|
*
|
|
|
|
* Any of the string modes above may specify encodings -
|
|
|
|
* either external encoding only or both external and internal encodings -
|
|
|
|
* by appending one or both encoding names, separated by colons:
|
|
|
|
*
|
|
|
|
* f = File.new('t.dat', 'rb')
|
|
|
|
* f.external_encoding # => #<Encoding:ASCII-8BIT>
|
|
|
|
* f.internal_encoding # => nil
|
|
|
|
* f = File.new('t.dat', 'rb:UTF-16')
|
|
|
|
* f.external_encoding # => #<Encoding:UTF-16 (dummy)>
|
|
|
|
* f.internal_encoding # => nil
|
|
|
|
* f = File.new('t.dat', 'rb:UTF-16:UTF-16')
|
|
|
|
* f.external_encoding # => #<Encoding:UTF-16 (dummy)>
|
|
|
|
* f.internal_encoding # => #<Encoding:UTF-16>
|
|
|
|
* f.close
|
|
|
|
*
|
|
|
|
* The numerous encoding names are available in array Encoding.name_list:
|
|
|
|
*
|
|
|
|
* Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
|
|
|
|
*
|
|
|
|
* When the external encoding is set, strings read are tagged by that encoding
|
|
|
|
* when reading, and strings written are converted to that encoding when
|
|
|
|
* writing.
|
|
|
|
*
|
|
|
|
* When both external and internal encodings are set,
|
|
|
|
* strings read are converted from external to internal encoding,
|
|
|
|
* and strings written are converted from internal to external encoding.
|
|
|
|
* For further details about transcoding input and output,
|
2022-11-09 19:15:39 +03:00
|
|
|
* see {Encodings}[rdoc-ref:encodings.rdoc@Encodings].
|
2022-09-22 00:34:55 +03:00
|
|
|
*
|
|
|
|
* If the external encoding is <tt>'BOM|UTF-8'</tt>, <tt>'BOM|UTF-16LE'</tt>
|
|
|
|
* or <tt>'BOM|UTF16-BE'</tt>,
|
|
|
|
* Ruby checks for a Unicode BOM in the input document
|
|
|
|
* to help determine the encoding.
|
|
|
|
* For UTF-16 encodings the file open mode must be binary.
|
|
|
|
* If the BOM is found,
|
|
|
|
* it is stripped and the external encoding from the BOM is used.
|
|
|
|
*
|
|
|
|
* Note that the BOM-style encoding option is case insensitive,
|
|
|
|
* so <tt>'bom|utf-8'</tt> is also valid.
|
|
|
|
*
|
2022-01-14 03:00:24 +03:00
|
|
|
* == \File Permissions
|
|
|
|
*
|
|
|
|
* A \File object has _permissions_, an octal integer representing
|
|
|
|
* the permissions of an actual file in the underlying platform.
|
|
|
|
*
|
|
|
|
* Note that file permissions are quite different from the _mode_
|
|
|
|
* of a file stream (\File object).
|
|
|
|
*
|
|
|
|
* In a \File object, the permissions are available thus,
|
|
|
|
* where method +mode+, despite its name, returns permissions:
|
|
|
|
*
|
|
|
|
* f = File.new('t.txt')
|
|
|
|
* f.lstat.mode.to_s(8) # => "100644"
|
|
|
|
*
|
|
|
|
* On a Unix-based operating system,
|
|
|
|
* the three low-order octal digits represent the permissions
|
|
|
|
* for owner (6), group (4), and world (4).
|
|
|
|
* The triplet of bits in each octal digit represent, respectively,
|
|
|
|
* read, write, and execute permissions.
|
|
|
|
*
|
|
|
|
* Permissions <tt>0644</tt> thus represent read-write access for owner
|
|
|
|
* and read-only access for group and world.
|
|
|
|
* See man pages {open(2)}[https://www.unix.com/man-page/bsd/2/open]
|
|
|
|
* and {chmod(2)}[https://www.unix.com/man-page/bsd/2/chmod].
|
|
|
|
*
|
|
|
|
* For a directory, the meaning of the execute bit changes:
|
|
|
|
* when set, the directory can be searched.
|
|
|
|
*
|
|
|
|
* Higher-order bits in permissions may indicate the type of file
|
|
|
|
* (plain, directory, pipe, socket, etc.) and various other special features.
|
|
|
|
*
|
|
|
|
* On non-Posix operating systems, permissions may include only read-only or read-write,
|
|
|
|
* in which case, the remaining permission will resemble typical values.
|
|
|
|
* On Windows, for instance, the default permissions are <code>0644</code>;
|
|
|
|
* The only change that can be made is to make the file
|
2003-12-21 10:28:54 +03:00
|
|
|
* read-only, which is reported as <code>0444</code>.
|
2013-09-14 01:08:36 +04:00
|
|
|
*
|
2022-01-14 03:00:24 +03:00
|
|
|
* For a method that actually creates a file in the underlying platform
|
|
|
|
* (as opposed to merely creating a \File object),
|
|
|
|
* permissions may be specified:
|
|
|
|
*
|
|
|
|
* File.new('t.tmp', File::CREAT, 0644)
|
|
|
|
* File.new('t.tmp', File::CREAT, 0444)
|
|
|
|
*
|
|
|
|
* Permissions may also be changed:
|
|
|
|
*
|
|
|
|
* f = File.new('t.tmp', File::CREAT, 0444)
|
|
|
|
* f.chmod(0644)
|
|
|
|
* f.chmod(0444)
|
|
|
|
*
|
2022-10-19 18:34:51 +03:00
|
|
|
* == \File \Constants
|
2022-01-14 03:00:24 +03:00
|
|
|
*
|
2023-08-12 19:44:38 +03:00
|
|
|
* Various constants for use in \File and IO methods
|
2022-01-14 03:00:24 +03:00
|
|
|
* may be found in module File::Constants;
|
|
|
|
* an array of their names is returned by <tt>File::Constants.constants</tt>.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
|
|
|
* == What's Here
|
|
|
|
*
|
|
|
|
* First, what's elsewhere. \Class \File:
|
|
|
|
*
|
2022-02-06 18:30:11 +03:00
|
|
|
* - Inherits from {class IO}[rdoc-ref:IO@What-27s+Here],
|
2021-05-18 16:27:41 +03:00
|
|
|
* in particular, methods for creating, reading, and writing files
|
2023-06-28 16:05:43 +03:00
|
|
|
* - Includes module FileTest,
|
2021-05-18 16:27:41 +03:00
|
|
|
* which provides dozens of additional methods.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
2021-05-18 16:27:41 +03:00
|
|
|
* Here, class \File provides methods that are useful for:
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
2022-02-06 18:37:06 +03:00
|
|
|
* - {Creating}[rdoc-ref:File@Creating]
|
|
|
|
* - {Querying}[rdoc-ref:File@Querying]
|
|
|
|
* - {Settings}[rdoc-ref:File@Settings]
|
|
|
|
* - {Other}[rdoc-ref:File@Other]
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
|
|
|
* === Creating
|
|
|
|
*
|
2022-03-25 20:16:37 +03:00
|
|
|
* - ::new: Opens the file at the given path; returns the file.
|
|
|
|
* - ::open: Same as ::new, but when given a block will yield the file to the block,
|
|
|
|
* and close the file upon exiting the block.
|
|
|
|
* - ::link: Creates a new name for an existing file using a hard link.
|
|
|
|
* - ::mkfifo: Returns the FIFO file created at the given path.
|
|
|
|
* - ::symlink: Creates a symbolic link for the given file path.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
|
|
|
* === Querying
|
|
|
|
*
|
|
|
|
* _Paths_
|
|
|
|
*
|
2022-03-25 20:16:37 +03:00
|
|
|
* - ::absolute_path: Returns the absolute file path for the given path.
|
|
|
|
* - ::absolute_path?: Returns whether the given path is the absolute file path.
|
|
|
|
* - ::basename: Returns the last component of the given file path.
|
|
|
|
* - ::dirname: Returns all but the last component of the given file path.
|
|
|
|
* - ::expand_path: Returns the absolute file path for the given path,
|
|
|
|
* expanding <tt>~</tt> for a home directory.
|
|
|
|
* - ::extname: Returns the file extension for the given file path.
|
|
|
|
* - ::fnmatch? (aliased as ::fnmatch): Returns whether the given file path
|
|
|
|
* matches the given pattern.
|
|
|
|
* - ::join: Joins path components into a single path string.
|
|
|
|
* - ::path: Returns the string representation of the given path.
|
|
|
|
* - ::readlink: Returns the path to the file at the given symbolic link.
|
|
|
|
* - ::realdirpath: Returns the real path for the given file path,
|
|
|
|
* where the last component need not exist.
|
|
|
|
* - ::realpath: Returns the real path for the given file path,
|
|
|
|
* where all components must exist.
|
|
|
|
* - ::split: Returns an array of two strings: the directory name and basename
|
|
|
|
* of the file at the given path.
|
|
|
|
* - #path (aliased as #to_path): Returns the string representation of the given path.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
|
|
|
* _Times_
|
|
|
|
*
|
2023-08-12 19:44:38 +03:00
|
|
|
* - ::atime: Returns a Time for the most recent access to the given file.
|
|
|
|
* - ::birthtime: Returns a Time for the creation of the given file.
|
|
|
|
* - ::ctime: Returns a Time for the metadata change of the given file.
|
|
|
|
* - ::mtime: Returns a Time for the most recent data modification to
|
2022-03-25 20:16:37 +03:00
|
|
|
* the content of the given file.
|
2023-08-12 19:44:38 +03:00
|
|
|
* - #atime: Returns a Time for the most recent access to +self+.
|
|
|
|
* - #birthtime: Returns a Time the creation for +self+.
|
|
|
|
* - #ctime: Returns a Time for the metadata change of +self+.
|
|
|
|
* - #mtime: Returns a Time for the most recent data modification
|
2022-03-25 20:16:37 +03:00
|
|
|
* to the content of +self+.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
|
|
|
* _Types_
|
|
|
|
*
|
2022-03-25 20:16:37 +03:00
|
|
|
* - ::blockdev?: Returns whether the file at the given path is a block device.
|
|
|
|
* - ::chardev?: Returns whether the file at the given path is a character device.
|
2022-11-21 08:07:18 +03:00
|
|
|
* - ::directory?: Returns whether the file at the given path is a directory.
|
2022-03-25 20:16:37 +03:00
|
|
|
* - ::executable?: Returns whether the file at the given path is executable
|
|
|
|
* by the effective user and group of the current process.
|
|
|
|
* - ::executable_real?: Returns whether the file at the given path is executable
|
|
|
|
* by the real user and group of the current process.
|
|
|
|
* - ::exist?: Returns whether the file at the given path exists.
|
|
|
|
* - ::file?: Returns whether the file at the given path is a regular file.
|
|
|
|
* - ::ftype: Returns a string giving the type of the file at the given path.
|
|
|
|
* - ::grpowned?: Returns whether the effective group of the current process
|
|
|
|
* owns the file at the given path.
|
|
|
|
* - ::identical?: Returns whether the files at two given paths are identical.
|
|
|
|
* - ::lstat: Returns the File::Stat object for the last symbolic link
|
|
|
|
* in the given path.
|
|
|
|
* - ::owned?: Returns whether the effective user of the current process
|
|
|
|
* owns the file at the given path.
|
|
|
|
* - ::pipe?: Returns whether the file at the given path is a pipe.
|
|
|
|
* - ::readable?: Returns whether the file at the given path is readable
|
|
|
|
* by the effective user and group of the current process.
|
|
|
|
* - ::readable_real?: Returns whether the file at the given path is readable
|
|
|
|
* by the real user and group of the current process.
|
|
|
|
* - ::setgid?: Returns whether the setgid bit is set for the file at the given path.
|
|
|
|
* - ::setuid?: Returns whether the setuid bit is set for the file at the given path.
|
|
|
|
* - ::socket?: Returns whether the file at the given path is a socket.
|
|
|
|
* - ::stat: Returns the File::Stat object for the file at the given path.
|
|
|
|
* - ::sticky?: Returns whether the file at the given path has its sticky bit set.
|
|
|
|
* - ::symlink?: Returns whether the file at the given path is a symbolic link.
|
|
|
|
* - ::umask: Returns the umask value for the current process.
|
|
|
|
* - ::world_readable?: Returns whether the file at the given path is readable
|
|
|
|
* by others.
|
|
|
|
* - ::world_writable?: Returns whether the file at the given path is writable
|
|
|
|
* by others.
|
|
|
|
* - ::writable?: Returns whether the file at the given path is writable
|
|
|
|
* by the effective user and group of the current process.
|
|
|
|
* - ::writable_real?: Returns whether the file at the given path is writable
|
|
|
|
* by the real user and group of the current process.
|
|
|
|
* - #lstat: Returns the File::Stat object for the last symbolic link
|
|
|
|
* in the path for +self+.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
|
|
|
* _Contents_
|
|
|
|
*
|
2022-03-25 20:16:37 +03:00
|
|
|
* - ::empty? (aliased as ::zero?): Returns whether the file at the given path
|
|
|
|
* exists and is empty.
|
|
|
|
* - ::size: Returns the size (bytes) of the file at the given path.
|
|
|
|
* - ::size?: Returns +nil+ if there is no file at the given path,
|
|
|
|
* or if that file is empty; otherwise returns the file size (bytes).
|
|
|
|
* - #size: Returns the size (bytes) of +self+.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
|
|
|
* === Settings
|
|
|
|
*
|
2022-03-25 20:16:37 +03:00
|
|
|
* - ::chmod: Changes permissions of the file at the given path.
|
|
|
|
* - ::chown: Change ownership of the file at the given path.
|
|
|
|
* - ::lchmod: Changes permissions of the last symbolic link in the given path.
|
|
|
|
* - ::lchown: Change ownership of the last symbolic in the given path.
|
|
|
|
* - ::lutime: For each given file path, sets the access time and modification time
|
|
|
|
* of the last symbolic link in the path.
|
|
|
|
* - ::rename: Moves the file at one given path to another given path.
|
|
|
|
* - ::utime: Sets the access time and modification time of each file
|
|
|
|
* at the given paths.
|
|
|
|
* - #flock: Locks or unlocks +self+.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
|
|
|
* === Other
|
|
|
|
*
|
2022-03-25 20:16:37 +03:00
|
|
|
* - ::truncate: Truncates the file at the given file path to the given size.
|
|
|
|
* - ::unlink (aliased as ::delete): Deletes the file for each given file path.
|
|
|
|
* - #truncate: Truncates +self+ to the given size.
|
2021-05-07 19:22:32 +03:00
|
|
|
*
|
2003-12-21 10:28:54 +03:00
|
|
|
*/
|
|
|
|
|
2001-01-10 10:52:46 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
Init_File(void)
|
1999-08-13 09:45:20 +04:00
|
|
|
{
|
2022-09-23 21:36:04 +03:00
|
|
|
#if defined(__APPLE__) && defined(HAVE_WORKING_FORK)
|
|
|
|
rb_CFString_class_initialize_before_fork();
|
|
|
|
#endif
|
|
|
|
|
2017-03-13 12:29:19 +03:00
|
|
|
VALUE separator;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_mFileTest = rb_define_module("FileTest");
|
|
|
|
rb_cFile = rb_define_class("File", rb_cIO);
|
2000-09-18 12:47:10 +04:00
|
|
|
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("directory?", rb_file_directory_p, 1);
|
|
|
|
define_filetest_function("exist?", rb_file_exist_p, 1);
|
|
|
|
define_filetest_function("readable?", rb_file_readable_p, 1);
|
|
|
|
define_filetest_function("readable_real?", rb_file_readable_real_p, 1);
|
2007-05-18 20:04:22 +04:00
|
|
|
define_filetest_function("world_readable?", rb_file_world_readable_p, 1);
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("writable?", rb_file_writable_p, 1);
|
2007-05-18 20:04:22 +04:00
|
|
|
define_filetest_function("writable_real?", rb_file_writable_real_p, 1);
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("world_writable?", rb_file_world_writable_p, 1);
|
|
|
|
define_filetest_function("executable?", rb_file_executable_p, 1);
|
|
|
|
define_filetest_function("executable_real?", rb_file_executable_real_p, 1);
|
|
|
|
define_filetest_function("file?", rb_file_file_p, 1);
|
|
|
|
define_filetest_function("zero?", rb_file_zero_p, 1);
|
2016-04-13 08:47:49 +03:00
|
|
|
define_filetest_function("empty?", rb_file_zero_p, 1);
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("size?", rb_file_size_p, 1);
|
2000-10-10 11:03:36 +04:00
|
|
|
define_filetest_function("size", rb_file_s_size, 1);
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("owned?", rb_file_owned_p, 1);
|
|
|
|
define_filetest_function("grpowned?", rb_file_grpowned_p, 1);
|
2000-09-18 12:47:10 +04:00
|
|
|
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("pipe?", rb_file_pipe_p, 1);
|
|
|
|
define_filetest_function("symlink?", rb_file_symlink_p, 1);
|
|
|
|
define_filetest_function("socket?", rb_file_socket_p, 1);
|
2000-09-18 12:47:10 +04:00
|
|
|
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("blockdev?", rb_file_blockdev_p, 1);
|
|
|
|
define_filetest_function("chardev?", rb_file_chardev_p, 1);
|
2000-09-18 12:47:10 +04:00
|
|
|
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("setuid?", rb_file_suid_p, 1);
|
|
|
|
define_filetest_function("setgid?", rb_file_sgid_p, 1);
|
|
|
|
define_filetest_function("sticky?", rb_file_sticky_p, 1);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2006-12-07 18:18:14 +03:00
|
|
|
define_filetest_function("identical?", rb_file_identical_p, 2);
|
2005-11-22 19:26:39 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "stat", rb_file_s_stat, 1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "ftype", rb_file_s_ftype, 1);
|
|
|
|
|
|
|
|
rb_define_singleton_method(rb_cFile, "atime", rb_file_s_atime, 1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "mtime", rb_file_s_mtime, 1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "ctime", rb_file_s_ctime, 1);
|
2014-05-22 15:49:22 +04:00
|
|
|
rb_define_singleton_method(rb_cFile, "birthtime", rb_file_s_birthtime, 1);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
|
|
|
rb_define_singleton_method(rb_cFile, "utime", rb_file_s_utime, -1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "chmod", rb_file_s_chmod, -1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "chown", rb_file_s_chown, -1);
|
2001-02-16 10:53:21 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "lchmod", rb_file_s_lchmod, -1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "lchown", rb_file_s_lchown, -1);
|
2017-11-29 12:59:20 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "lutime", rb_file_s_lutime, -1);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
|
|
|
rb_define_singleton_method(rb_cFile, "link", rb_file_s_link, 2);
|
|
|
|
rb_define_singleton_method(rb_cFile, "symlink", rb_file_s_symlink, 2);
|
|
|
|
rb_define_singleton_method(rb_cFile, "readlink", rb_file_s_readlink, 1);
|
|
|
|
|
2016-04-11 00:54:41 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "unlink", rb_file_s_unlink, -1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "delete", rb_file_s_unlink, -1);
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "rename", rb_file_s_rename, 2);
|
|
|
|
rb_define_singleton_method(rb_cFile, "umask", rb_file_s_umask, -1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "truncate", rb_file_s_truncate, 2);
|
2015-09-18 14:11:14 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "mkfifo", rb_file_s_mkfifo, -1);
|
2019-08-29 05:47:20 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "expand_path", s_expand_path, -1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "absolute_path", s_absolute_path, -1);
|
2019-09-05 14:00:50 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "absolute_path?", s_absolute_path_p, 1);
|
2010-03-07 07:55:34 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "realpath", rb_file_s_realpath, -1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "realdirpath", rb_file_s_realdirpath, -1);
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "basename", rb_file_s_basename, -1);
|
2016-03-18 10:40:45 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "dirname", rb_file_s_dirname, -1);
|
2002-04-10 12:45:26 +04:00
|
|
|
rb_define_singleton_method(rb_cFile, "extname", rb_file_s_extname, 1);
|
2004-04-07 06:51:05 +04:00
|
|
|
rb_define_singleton_method(rb_cFile, "path", rb_file_s_path, 1);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2018-10-13 12:59:22 +03:00
|
|
|
separator = rb_fstring_lit("/");
|
2013-06-02 07:12:04 +04:00
|
|
|
/* separates directory parts in path */
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_const(rb_cFile, "Separator", separator);
|
2018-02-23 05:18:52 +03:00
|
|
|
/* separates directory parts in path */
|
1999-08-13 09:45:20 +04:00
|
|
|
rb_define_const(rb_cFile, "SEPARATOR", separator);
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1);
|
|
|
|
rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2);
|
|
|
|
|
2010-03-15 01:51:08 +03:00
|
|
|
#ifdef DOSISH
|
2013-06-02 07:12:04 +04:00
|
|
|
/* platform specific alternative separator */
|
2010-03-15 01:16:12 +03:00
|
|
|
rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_obj_freeze(rb_usascii_str_new2(file_alt_separator)));
|
1999-08-13 09:45:20 +04:00
|
|
|
#else
|
|
|
|
rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
|
|
|
|
#endif
|
2013-06-02 07:12:04 +04:00
|
|
|
/* path list separator */
|
2017-03-17 03:55:45 +03:00
|
|
|
rb_define_const(rb_cFile, "PATH_SEPARATOR", rb_fstring_cstr(PATH_SEP));
|
1999-01-20 07:59:39 +03:00
|
|
|
|
|
|
|
rb_define_method(rb_cIO, "stat", rb_io_stat, 0); /* this is IO's method */
|
|
|
|
rb_define_method(rb_cFile, "lstat", rb_file_lstat, 0);
|
|
|
|
|
|
|
|
rb_define_method(rb_cFile, "atime", rb_file_atime, 0);
|
|
|
|
rb_define_method(rb_cFile, "mtime", rb_file_mtime, 0);
|
|
|
|
rb_define_method(rb_cFile, "ctime", rb_file_ctime, 0);
|
2014-05-22 15:49:22 +04:00
|
|
|
rb_define_method(rb_cFile, "birthtime", rb_file_birthtime, 0);
|
2021-07-02 13:41:16 +03:00
|
|
|
rb_define_method(rb_cFile, "size", file_size, 0);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
|
|
|
rb_define_method(rb_cFile, "chmod", rb_file_chmod, 1);
|
|
|
|
rb_define_method(rb_cFile, "chown", rb_file_chown, 2);
|
|
|
|
rb_define_method(rb_cFile, "truncate", rb_file_truncate, 1);
|
|
|
|
|
|
|
|
rb_define_method(rb_cFile, "flock", rb_file_flock, 1);
|
|
|
|
|
2012-11-20 09:00:45 +04:00
|
|
|
/*
|
|
|
|
* Document-module: File::Constants
|
|
|
|
*
|
2023-07-23 17:24:19 +03:00
|
|
|
* \Module +File::Constants+ defines file-related constants.
|
2012-11-20 09:00:45 +04:00
|
|
|
*
|
2023-07-23 17:24:19 +03:00
|
|
|
* There are two families of constants here:
|
|
|
|
*
|
|
|
|
* - Those having to do with {file access}[rdoc-ref:File::Constants@File+Access].
|
2023-08-31 17:27:10 +03:00
|
|
|
* - Those having to do with {filename globbing}[rdoc-ref:File::Constants@Filename+Globbing+Constants+-28File-3A-3AFNM_-2A-29].
|
2023-07-23 17:24:19 +03:00
|
|
|
*
|
|
|
|
* \File constants defined for the local process may be retrieved
|
|
|
|
* with method File::Constants.constants:
|
|
|
|
*
|
|
|
|
* File::Constants.constants.take(5)
|
|
|
|
* # => [:RDONLY, :WRONLY, :RDWR, :APPEND, :CREAT]
|
|
|
|
*
|
|
|
|
* == \File Access
|
|
|
|
*
|
|
|
|
* \File-access constants may be used with optional argument +mode+ in calls
|
|
|
|
* to the following methods:
|
|
|
|
*
|
|
|
|
* - File.new.
|
|
|
|
* - File.open.
|
|
|
|
* - IO.for_fd.
|
|
|
|
* - IO.new.
|
|
|
|
* - IO.open.
|
|
|
|
* - IO.popen.
|
|
|
|
* - IO.reopen.
|
|
|
|
* - IO.sysopen.
|
|
|
|
* - StringIO.new.
|
|
|
|
* - StringIO.open.
|
|
|
|
* - StringIO#reopen.
|
|
|
|
*
|
|
|
|
* === Read/Write Access
|
|
|
|
*
|
|
|
|
* Read-write access for a stream
|
|
|
|
* may be specified by a file-access constant.
|
|
|
|
*
|
|
|
|
* The constant may be specified as part of a bitwise OR of other such constants.
|
|
|
|
*
|
|
|
|
* Any combination of the constants in this section may be specified.
|
|
|
|
*
|
|
|
|
* ==== File::RDONLY
|
|
|
|
*
|
|
|
|
* Flag File::RDONLY specifies the the stream should be opened for reading only:
|
|
|
|
*
|
|
|
|
* filepath = '/tmp/t.tmp'
|
|
|
|
* f = File.new(filepath, File::RDONLY)
|
|
|
|
* f.write('Foo') # Raises IOError (not opened for writing).
|
|
|
|
*
|
|
|
|
* ==== File::WRONLY
|
|
|
|
*
|
|
|
|
* Flag File::WRONLY specifies that the stream should be opened for writing only:
|
|
|
|
*
|
|
|
|
* f = File.new(filepath, File::WRONLY)
|
|
|
|
* f.read # Raises IOError (not opened for reading).
|
|
|
|
*
|
|
|
|
* ==== File::RDWR
|
|
|
|
*
|
|
|
|
* Flag File::RDWR specifies that the stream should be opened
|
|
|
|
* for both reading and writing:
|
|
|
|
*
|
|
|
|
* f = File.new(filepath, File::RDWR)
|
|
|
|
* f.write('Foo') # => 3
|
|
|
|
* f.rewind # => 0
|
|
|
|
* f.read # => "Foo"
|
|
|
|
*
|
|
|
|
* === \File Positioning
|
|
|
|
*
|
|
|
|
* ==== File::APPEND
|
|
|
|
*
|
|
|
|
* Flag File::APPEND specifies that the stream should be opened
|
|
|
|
* in append mode.
|
|
|
|
*
|
|
|
|
* Before each write operation, the position is set to end-of-stream.
|
|
|
|
* The modification of the position and the following write operation
|
|
|
|
* are performed as a single atomic step.
|
|
|
|
*
|
|
|
|
* ==== File::TRUNC
|
|
|
|
*
|
|
|
|
* Flag File::TRUNC specifies that the stream should be truncated
|
|
|
|
* at its beginning.
|
|
|
|
* If the file exists and is successfully opened for writing,
|
|
|
|
* it is to be truncated to position zero;
|
|
|
|
* its ctime and mtime are updated.
|
|
|
|
*
|
|
|
|
* There is no effect on a FIFO special file or a terminal device.
|
|
|
|
* The effect on other file types is implementation-defined.
|
|
|
|
* The result of using File::TRUNC with File::RDONLY is undefined.
|
|
|
|
*
|
|
|
|
* === Creating and Preserving
|
|
|
|
*
|
|
|
|
* ==== File::CREAT
|
|
|
|
*
|
|
|
|
* Flag File::CREAT specifies that the stream should be created
|
|
|
|
* if it does not already exist.
|
|
|
|
*
|
|
|
|
* If the file exists:
|
|
|
|
*
|
|
|
|
* - Raise an exception if File::EXCL is also specified.
|
|
|
|
* - Otherwise, do nothing.
|
|
|
|
*
|
|
|
|
* If the file does not exist, then it is created.
|
|
|
|
* Upon successful completion, the atime, ctime, and mtime of the file are updated,
|
|
|
|
* and the ctime and mtime of the parent directory are updated.
|
|
|
|
*
|
|
|
|
* ==== File::EXCL
|
|
|
|
*
|
|
|
|
* Flag File::EXCL specifies that the stream should not already exist;
|
|
|
|
* If flags File::CREAT and File::EXCL are both specified
|
|
|
|
* and the stream already exists, an exception is raised.
|
|
|
|
*
|
|
|
|
* The check for the existence and creation of the file is performed as an
|
|
|
|
* atomic operation.
|
|
|
|
*
|
|
|
|
* If both File::EXCL and File::CREAT are specified and the path names a symbolic link,
|
|
|
|
* an exception is raised regardless of the contents of the symbolic link.
|
|
|
|
*
|
|
|
|
* If File::EXCL is specified and File::CREAT is not specified,
|
|
|
|
* the result is undefined.
|
|
|
|
*
|
|
|
|
* === POSIX \File \Constants
|
|
|
|
*
|
|
|
|
* Some file-access constants are defined only on POSIX-compliant systems;
|
|
|
|
* those are:
|
|
|
|
*
|
|
|
|
* - File::SYNC.
|
|
|
|
* - File::DSYNC.
|
|
|
|
* - File::RSYNC.
|
|
|
|
* - File::DIRECT.
|
|
|
|
* - File::NOATIME.
|
|
|
|
* - File::NOCTTY.
|
|
|
|
* - File::NOFOLLOW.
|
|
|
|
* - File::TMPFILE.
|
|
|
|
*
|
|
|
|
* ==== File::SYNC, File::RSYNC, and File::DSYNC
|
|
|
|
*
|
|
|
|
* Flag File::SYNC, File::RSYNC, or File::DSYNC
|
|
|
|
* specifies synchronization of I/O operations with the underlying file system.
|
|
|
|
*
|
|
|
|
* These flags are valid only for POSIX-compliant systems.
|
|
|
|
*
|
|
|
|
* - File::SYNC specifies that all write operations (both data and metadata)
|
|
|
|
* are immediately to be flushed to the underlying storage device.
|
|
|
|
* This means that the data is written to the storage device,
|
|
|
|
* and the file's metadata (e.g., file size, timestamps, permissions)
|
|
|
|
* are also synchronized.
|
|
|
|
* This guarantees that data is safely stored on the storage medium
|
|
|
|
* before returning control to the calling program.
|
|
|
|
* This flag can have a significant impact on performance
|
|
|
|
* since it requires synchronous writes, which can be slower
|
|
|
|
* compared to asynchronous writes.
|
|
|
|
*
|
|
|
|
* - File::RSYNC specifies that any read operations on the file will not return
|
|
|
|
* until all outstanding write operations
|
|
|
|
* (those that have been issued but not completed) are also synchronized.
|
|
|
|
* This is useful when you want to read the most up-to-date data,
|
|
|
|
* which may still be in the process of being written.
|
|
|
|
*
|
|
|
|
* - File::DSYNC specifies that all _data_ write operations
|
|
|
|
* are immediately to be flushed to the underlying storage device;
|
|
|
|
* this differs from File::SYNC, which requires that _metadata_
|
|
|
|
* also be synchronized.
|
|
|
|
*
|
|
|
|
* Note that the behavior of these flags may vary slightly
|
|
|
|
* depending on the operating system and filesystem being used.
|
|
|
|
* Additionally, using these flags can have an impact on performance
|
|
|
|
* due to the synchronous nature of the I/O operations,
|
|
|
|
* so they should be used judiciously,
|
|
|
|
* especially in performance-critical applications.
|
|
|
|
*
|
|
|
|
* ==== File::NOCTTY
|
|
|
|
*
|
|
|
|
* Flag File::NOCTTY specifies that if the stream is a terminal device,
|
|
|
|
* that device does not become the controlling terminal for the process.
|
|
|
|
*
|
|
|
|
* Defined only for POSIX-compliant systems.
|
|
|
|
*
|
|
|
|
* ==== File::DIRECT
|
|
|
|
*
|
|
|
|
* Flag File::DIRECT requests that cache effects of the I/O to and from the stream
|
|
|
|
* be minimized.
|
|
|
|
*
|
|
|
|
* Defined only for POSIX-compliant systems.
|
|
|
|
*
|
|
|
|
* ==== File::NOATIME
|
|
|
|
*
|
|
|
|
* Flag File::NOATIME specifies that act of opening the stream
|
|
|
|
* should not modify its access time (atime).
|
|
|
|
*
|
|
|
|
* Defined only for POSIX-compliant systems.
|
|
|
|
*
|
|
|
|
* ==== File::NOFOLLOW
|
|
|
|
*
|
|
|
|
* Flag File::NOFOLLOW specifies that if path is a symbolic link,
|
|
|
|
* it should not be followed.
|
|
|
|
*
|
|
|
|
* Defined only for POSIX-compliant systems.
|
|
|
|
*
|
|
|
|
* ==== File::TMPFILE
|
|
|
|
*
|
|
|
|
* Flag File::TMPFILE specifies that the opened stream
|
|
|
|
* should be a new temporary file.
|
|
|
|
*
|
|
|
|
* Defined only for POSIX-compliant systems.
|
|
|
|
*
|
|
|
|
* === Other File-Access \Constants
|
|
|
|
*
|
|
|
|
* ==== File::NONBLOCK
|
|
|
|
*
|
|
|
|
* When possible, the file is opened in nonblocking mode.
|
|
|
|
* Neither the open operation nor any subsequent I/O operations on
|
|
|
|
* the file will cause the calling process to wait.
|
|
|
|
*
|
|
|
|
* ==== File::BINARY
|
|
|
|
*
|
|
|
|
* Flag File::BINARY specifies that the stream is to be accessed in binary mode.
|
|
|
|
*
|
|
|
|
* ==== File::SHARE_DELETE (Windows Only)
|
|
|
|
*
|
|
|
|
* Flag File::SHARE_DELETE enables other processes to open the stream
|
|
|
|
* with delete access.
|
|
|
|
*
|
|
|
|
* If the stream is opened for (local) delete access without File::SHARE_DELETE,
|
|
|
|
* and another process attempts to open it with delete access,
|
|
|
|
* the attempt fails and the stream is not opened for that process.
|
|
|
|
*
|
|
|
|
* == Locking
|
|
|
|
*
|
|
|
|
* Four file constants relate to stream locking;
|
|
|
|
* see File#flock:
|
|
|
|
*
|
|
|
|
* ==== File::LOCK_EX
|
|
|
|
*
|
|
|
|
* Flag File::LOCK_EX specifies an exclusive lock;
|
|
|
|
* only one process a a time may lock the stream.
|
|
|
|
*
|
|
|
|
* ==== File::LOCK_NB
|
|
|
|
*
|
|
|
|
* Flag File::LOCK_NB specifies non-blocking locking for the stream;
|
|
|
|
* may be combined with File::LOCK_EX or File::LOCK_SH.
|
|
|
|
*
|
|
|
|
* ==== File::LOCK_SH
|
|
|
|
*
|
|
|
|
* Flag File::LOCK_SH specifies that multiple processes may lock
|
|
|
|
* the stream at the same time.
|
|
|
|
*
|
|
|
|
* ==== File::LOCK_UN
|
|
|
|
*
|
|
|
|
* Flag File::LOCK_UN specifies that the stream is not to be locked.
|
|
|
|
*
|
|
|
|
* == Filename Globbing \Constants (File::FNM_*)
|
|
|
|
*
|
|
|
|
* Filename-globbing constants may be used with optional argument +flags+
|
|
|
|
* in calls to the following methods:
|
|
|
|
*
|
|
|
|
* - Dir.glob.
|
|
|
|
* - File.fnmatch.
|
|
|
|
* - Pathname#fnmatch.
|
|
|
|
* - Pathname.glob.
|
|
|
|
* - Pathname#glob.
|
|
|
|
*
|
|
|
|
* The constants are:
|
|
|
|
*
|
|
|
|
* ==== File::FNM_CASEFOLD
|
|
|
|
*
|
|
|
|
* Flag File::FNM_CASEFOLD makes patterns case insensitive
|
|
|
|
* for File.fnmatch (but not Dir.glob).
|
|
|
|
*
|
|
|
|
* ==== File::FNM_DOTMATCH
|
|
|
|
*
|
|
|
|
* Flag File::FNM_DOTMATCH makes the <tt>'*'</tt> pattern
|
|
|
|
* match a filename starting with <tt>'.'</tt>.
|
|
|
|
*
|
|
|
|
* ==== File::FNM_EXTGLOB
|
|
|
|
*
|
|
|
|
* Flag File::FNM_EXTGLOB enables pattern <tt>'{_a_,_b_}'</tt>,
|
|
|
|
* which matches pattern '_a_' and pattern '_b_';
|
|
|
|
* behaves like
|
2023-07-23 04:19:50 +03:00
|
|
|
* a {regexp union}[rdoc-ref:Regexp.union]
|
2023-07-23 17:24:19 +03:00
|
|
|
* (e.g., <tt>'(?:_a_|_b_)'</tt>):
|
|
|
|
*
|
|
|
|
* pattern = '{LEGAL,BSDL}'
|
|
|
|
* Dir.glob(pattern) # => ["LEGAL", "BSDL"]
|
|
|
|
* Pathname.glob(pattern) # => [#<Pathname:LEGAL>, #<Pathname:BSDL>]
|
|
|
|
* pathname.glob(pattern) # => [#<Pathname:LEGAL>, #<Pathname:BSDL>]
|
|
|
|
*
|
|
|
|
* ==== File::FNM_NOESCAPE
|
|
|
|
*
|
|
|
|
* Flag File::FNM_NOESCAPE disables <tt>'\'</tt> escaping.
|
|
|
|
*
|
|
|
|
* ==== File::FNM_PATHNAME
|
|
|
|
*
|
|
|
|
* Flag File::FNM_PATHNAME specifies that patterns <tt>'*'</tt> and <tt>'?'</tt>
|
|
|
|
* do not match the directory separator
|
|
|
|
* (the value of constant File::SEPARATOR).
|
|
|
|
*
|
|
|
|
* ==== File::FNM_SHORTNAME (Windows Only)
|
|
|
|
*
|
|
|
|
* Flag File::FNM_SHORTNAME Allows patterns to match short names if they exist.
|
|
|
|
*
|
|
|
|
* ==== File::FNM_SYSCASE
|
|
|
|
*
|
|
|
|
* Flag File::FNM_SYSCASE specifies that case sensitivity
|
|
|
|
* is the same as in the underlying operating system;
|
|
|
|
* effective for File.fnmatch, but not Dir.glob.
|
|
|
|
*
|
|
|
|
* == Other \Constants
|
|
|
|
*
|
|
|
|
* ==== File::NULL
|
|
|
|
*
|
|
|
|
* Flag File::NULL contains the string value of the null device:
|
|
|
|
*
|
|
|
|
* - On a Unix-like OS, <tt>'/dev/null'</tt>.
|
|
|
|
* - On Windows, <tt>'NUL'</tt>.
|
2012-11-20 09:00:45 +04:00
|
|
|
*
|
|
|
|
*/
|
2000-09-25 13:15:08 +04:00
|
|
|
rb_mFConst = rb_define_module_under(rb_cFile, "Constants");
|
2003-07-28 18:23:12 +04:00
|
|
|
rb_include_module(rb_cIO, rb_mFConst);
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::RDONLY}[rdoc-ref:File::Constants@File-3A-3ARDONLY] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "RDONLY", INT2FIX(O_RDONLY));
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::WRONLY}[rdoc-ref:File::Constants@File-3A-3AWRONLY] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "WRONLY", INT2FIX(O_WRONLY));
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::RDWR}[rdoc-ref:File::Constants@File-3A-3ARDWR] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "RDWR", INT2FIX(O_RDWR));
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::APPEND}[rdoc-ref:File::Constants@File-3A-3AAPPEND] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "APPEND", INT2FIX(O_APPEND));
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::CREAT}[rdoc-ref:File::Constants@File-3A-3ACREAT] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "CREAT", INT2FIX(O_CREAT));
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::EXCL}[rdoc-ref:File::Constants@File-3A-3AEXCL] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "EXCL", INT2FIX(O_EXCL));
|
|
|
|
#if defined(O_NDELAY) || defined(O_NONBLOCK)
|
|
|
|
# ifndef O_NONBLOCK
|
|
|
|
# define O_NONBLOCK O_NDELAY
|
|
|
|
# endif
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::NONBLOCK}[rdoc-ref:File::Constants@File-3A-3ANONBLOCK] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "NONBLOCK", INT2FIX(O_NONBLOCK));
|
|
|
|
#endif
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::TRUNC}[rdoc-ref:File::Constants@File-3A-3ATRUNC] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "TRUNC", INT2FIX(O_TRUNC));
|
|
|
|
#ifdef O_NOCTTY
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::NOCTTY}[rdoc-ref:File::Constants@File-3A-3ANOCTTY] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "NOCTTY", INT2FIX(O_NOCTTY));
|
|
|
|
#endif
|
|
|
|
#ifndef O_BINARY
|
|
|
|
# define O_BINARY 0
|
|
|
|
#endif
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::BINARY}[rdoc-ref:File::Constants@File-3A-3ABINARY] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "BINARY", INT2FIX(O_BINARY));
|
2015-06-12 15:14:06 +03:00
|
|
|
#ifndef O_SHARE_DELETE
|
|
|
|
# define O_SHARE_DELETE 0
|
|
|
|
#endif
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::SHARE_DELETE}[rdoc-ref:File::Constants@File-3A-3ASHARE_DELETE+-28Windows+Only-29] */
|
2015-06-12 15:14:06 +03:00
|
|
|
rb_define_const(rb_mFConst, "SHARE_DELETE", INT2FIX(O_SHARE_DELETE));
|
2012-11-20 09:00:45 +04:00
|
|
|
#ifdef O_SYNC
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::SYNC}[rdoc-ref:File::Constants@File-3A-3ASYNC-2C+File-3A-3ARSYNC-2C+and+File-3A-3ADSYNC] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "SYNC", INT2FIX(O_SYNC));
|
|
|
|
#endif
|
|
|
|
#ifdef O_DSYNC
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::DSYNC}[rdoc-ref:File::Constants@File-3A-3ASYNC-2C+File-3A-3ARSYNC-2C+and+File-3A-3ADSYNC] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "DSYNC", INT2FIX(O_DSYNC));
|
|
|
|
#endif
|
|
|
|
#ifdef O_RSYNC
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::RSYNC}[rdoc-ref:File::Constants@File-3A-3ASYNC-2C+File-3A-3ARSYNC-2C+and+File-3A-3ADSYNC] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "RSYNC", INT2FIX(O_RSYNC));
|
|
|
|
#endif
|
|
|
|
#ifdef O_NOFOLLOW
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::NOFOLLOW}[rdoc-ref:File::Constants@File-3A-3ANOFOLLOW] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "NOFOLLOW", INT2FIX(O_NOFOLLOW)); /* FreeBSD, Linux */
|
|
|
|
#endif
|
|
|
|
#ifdef O_NOATIME
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::NOATIME}[rdoc-ref:File::Constants@File-3A-3ANOATIME] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "NOATIME", INT2FIX(O_NOATIME)); /* Linux */
|
|
|
|
#endif
|
|
|
|
#ifdef O_DIRECT
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::DIRECT}[rdoc-ref:File::Constants@File-3A-3ADIRECT] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "DIRECT", INT2FIX(O_DIRECT));
|
|
|
|
#endif
|
2015-11-08 09:26:44 +03:00
|
|
|
#ifdef O_TMPFILE
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::TMPFILE}[rdoc-ref:File::Constants@File-3A-3ATMPFILE] */
|
2015-11-08 09:26:44 +03:00
|
|
|
rb_define_const(rb_mFConst, "TMPFILE", INT2FIX(O_TMPFILE));
|
|
|
|
#endif
|
2012-11-20 09:00:45 +04:00
|
|
|
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::LOCK_SH}[rdoc-ref:File::Constants@File-3A-3ALOCK_SH] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "LOCK_SH", INT2FIX(LOCK_SH));
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::LOCK_EX}[rdoc-ref:File::Constants@File-3A-3ALOCK_EX] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "LOCK_EX", INT2FIX(LOCK_EX));
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::LOCK_UN}[rdoc-ref:File::Constants@File-3A-3ALOCK_UN] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "LOCK_UN", INT2FIX(LOCK_UN));
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::LOCK_NB}[rdoc-ref:File::Constants@File-3A-3ALOCK_NB] */
|
2012-11-20 09:00:45 +04:00
|
|
|
rb_define_const(rb_mFConst, "LOCK_NB", INT2FIX(LOCK_NB));
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2023-12-18 13:42:57 +03:00
|
|
|
/* {File::NULL}[rdoc-ref:File::Constants@File-3A-3ANULL] */
|
2018-02-07 02:40:19 +03:00
|
|
|
rb_define_const(rb_mFConst, "NULL", rb_fstring_cstr(ruby_null_device));
|
2010-08-27 10:26:41 +04:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_global_function("test", rb_f_test, -1);
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
rb_cStat = rb_define_class_under(rb_cFile, "Stat", rb_cObject);
|
2002-12-20 11:33:17 +03:00
|
|
|
rb_define_alloc_func(rb_cStat, rb_stat_s_alloc);
|
2001-05-02 08:22:21 +04:00
|
|
|
rb_define_method(rb_cStat, "initialize", rb_stat_init, 1);
|
2003-05-19 09:41:08 +04:00
|
|
|
rb_define_method(rb_cStat, "initialize_copy", rb_stat_init_copy, 1);
|
1999-12-01 12:24:48 +03:00
|
|
|
|
|
|
|
rb_include_module(rb_cStat, rb_mComparable);
|
|
|
|
|
|
|
|
rb_define_method(rb_cStat, "<=>", rb_stat_cmp, 1);
|
|
|
|
|
|
|
|
rb_define_method(rb_cStat, "dev", rb_stat_dev, 0);
|
2004-07-17 06:23:52 +04:00
|
|
|
rb_define_method(rb_cStat, "dev_major", rb_stat_dev_major, 0);
|
|
|
|
rb_define_method(rb_cStat, "dev_minor", rb_stat_dev_minor, 0);
|
1999-12-01 12:24:48 +03:00
|
|
|
rb_define_method(rb_cStat, "ino", rb_stat_ino, 0);
|
|
|
|
rb_define_method(rb_cStat, "mode", rb_stat_mode, 0);
|
|
|
|
rb_define_method(rb_cStat, "nlink", rb_stat_nlink, 0);
|
|
|
|
rb_define_method(rb_cStat, "uid", rb_stat_uid, 0);
|
|
|
|
rb_define_method(rb_cStat, "gid", rb_stat_gid, 0);
|
|
|
|
rb_define_method(rb_cStat, "rdev", rb_stat_rdev, 0);
|
2002-01-29 10:16:09 +03:00
|
|
|
rb_define_method(rb_cStat, "rdev_major", rb_stat_rdev_major, 0);
|
|
|
|
rb_define_method(rb_cStat, "rdev_minor", rb_stat_rdev_minor, 0);
|
1999-12-01 12:24:48 +03:00
|
|
|
rb_define_method(rb_cStat, "size", rb_stat_size, 0);
|
|
|
|
rb_define_method(rb_cStat, "blksize", rb_stat_blksize, 0);
|
|
|
|
rb_define_method(rb_cStat, "blocks", rb_stat_blocks, 0);
|
|
|
|
rb_define_method(rb_cStat, "atime", rb_stat_atime, 0);
|
|
|
|
rb_define_method(rb_cStat, "mtime", rb_stat_mtime, 0);
|
|
|
|
rb_define_method(rb_cStat, "ctime", rb_stat_ctime, 0);
|
2014-05-22 15:49:22 +04:00
|
|
|
rb_define_method(rb_cStat, "birthtime", rb_stat_birthtime, 0);
|
1999-12-01 12:24:48 +03:00
|
|
|
|
2000-06-19 12:38:11 +04:00
|
|
|
rb_define_method(rb_cStat, "inspect", rb_stat_inspect, 0);
|
|
|
|
|
1999-12-01 12:24:48 +03:00
|
|
|
rb_define_method(rb_cStat, "ftype", rb_stat_ftype, 0);
|
|
|
|
|
|
|
|
rb_define_method(rb_cStat, "directory?", rb_stat_d, 0);
|
|
|
|
rb_define_method(rb_cStat, "readable?", rb_stat_r, 0);
|
|
|
|
rb_define_method(rb_cStat, "readable_real?", rb_stat_R, 0);
|
2004-01-19 12:19:31 +03:00
|
|
|
rb_define_method(rb_cStat, "world_readable?", rb_stat_wr, 0);
|
1999-12-01 12:24:48 +03:00
|
|
|
rb_define_method(rb_cStat, "writable?", rb_stat_w, 0);
|
|
|
|
rb_define_method(rb_cStat, "writable_real?", rb_stat_W, 0);
|
2004-01-19 12:19:31 +03:00
|
|
|
rb_define_method(rb_cStat, "world_writable?", rb_stat_ww, 0);
|
1999-12-01 12:24:48 +03:00
|
|
|
rb_define_method(rb_cStat, "executable?", rb_stat_x, 0);
|
|
|
|
rb_define_method(rb_cStat, "executable_real?", rb_stat_X, 0);
|
|
|
|
rb_define_method(rb_cStat, "file?", rb_stat_f, 0);
|
|
|
|
rb_define_method(rb_cStat, "zero?", rb_stat_z, 0);
|
|
|
|
rb_define_method(rb_cStat, "size?", rb_stat_s, 0);
|
|
|
|
rb_define_method(rb_cStat, "owned?", rb_stat_owned, 0);
|
|
|
|
rb_define_method(rb_cStat, "grpowned?", rb_stat_grpowned, 0);
|
|
|
|
|
|
|
|
rb_define_method(rb_cStat, "pipe?", rb_stat_p, 0);
|
|
|
|
rb_define_method(rb_cStat, "symlink?", rb_stat_l, 0);
|
|
|
|
rb_define_method(rb_cStat, "socket?", rb_stat_S, 0);
|
|
|
|
|
|
|
|
rb_define_method(rb_cStat, "blockdev?", rb_stat_b, 0);
|
|
|
|
rb_define_method(rb_cStat, "chardev?", rb_stat_c, 0);
|
|
|
|
|
|
|
|
rb_define_method(rb_cStat, "setuid?", rb_stat_suid, 0);
|
|
|
|
rb_define_method(rb_cStat, "setgid?", rb_stat_sgid, 0);
|
|
|
|
rb_define_method(rb_cStat, "sticky?", rb_stat_sticky, 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|