2000-05-01 13:42:38 +04:00
|
|
|
/**********************************************************************
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
dir.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
created at: Wed Jan 5 09:51:01 JST 1994
|
|
|
|
|
* 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"
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2019-12-04 11:16:30 +03:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
#include <sys/types.h>
|
1998-01-16 15:19:22 +03:00
|
|
|
#include <sys/stat.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2018-06-22 11:47:12 +03:00
|
|
|
#ifndef O_CLOEXEC
|
|
|
|
# define O_CLOEXEC 0
|
|
|
|
#endif
|
|
|
|
|
2017-05-23 17:34:12 +03:00
|
|
|
#ifndef USE_OPENDIR_AT
|
|
|
|
# if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD) && \
|
|
|
|
defined(HAVE_OPENAT) && defined(HAVE_FSTATAT)
|
|
|
|
# define USE_OPENDIR_AT 1
|
|
|
|
# else
|
|
|
|
# define USE_OPENDIR_AT 0
|
|
|
|
# endif
|
|
|
|
#endif
|
2019-12-04 11:16:30 +03:00
|
|
|
|
2017-05-23 17:34:12 +03:00
|
|
|
#if USE_OPENDIR_AT
|
|
|
|
# include <fcntl.h>
|
|
|
|
#endif
|
|
|
|
|
2016-02-16 11:34:47 +03:00
|
|
|
#undef HAVE_DIRENT_NAMLEN
|
* 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_DIRENT_H && !defined _WIN32
|
1998-01-16 15:13:05 +03:00
|
|
|
# include <dirent.h>
|
|
|
|
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
* 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_DIRECT_H && !defined _WIN32
|
1999-01-20 07:59:39 +03:00
|
|
|
# include <direct.h>
|
|
|
|
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
1998-01-16 15:13:05 +03:00
|
|
|
#else
|
|
|
|
# define dirent direct
|
2011-09-26 04:19:03 +04:00
|
|
|
# define NAMLEN(dirent) (dirent)->d_namlen
|
2016-02-16 11:34:47 +03:00
|
|
|
# define HAVE_DIRENT_NAMLEN 1
|
2021-04-29 16:12:44 +03:00
|
|
|
# ifdef HAVE_SYS_NDIR_H
|
1998-01-16 15:13:05 +03:00
|
|
|
# include <sys/ndir.h>
|
|
|
|
# endif
|
2021-04-29 16:12:44 +03:00
|
|
|
# ifdef HAVE_SYS_DIR_H
|
1998-01-16 15:13:05 +03:00
|
|
|
# include <sys/dir.h>
|
|
|
|
# endif
|
2021-04-29 16:12:44 +03:00
|
|
|
# ifdef HAVE_NDIR_H
|
1998-01-16 15:13:05 +03:00
|
|
|
# include <ndir.h>
|
|
|
|
# endif
|
* 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
|
2001-03-19 06:20:24 +03:00
|
|
|
# include "win32/dir.h"
|
1998-01-16 15:13:05 +03:00
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
#ifndef HAVE_STDLIB_H
|
1998-01-16 15:13:05 +03:00
|
|
|
char *getenv();
|
|
|
|
#endif
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
#ifndef HAVE_STRING_H
|
* 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
|
|
|
char *strchr(char*,char);
|
1999-01-20 07:59:39 +03:00
|
|
|
#endif
|
|
|
|
|
2014-12-25 09:36:18 +03:00
|
|
|
#ifdef HAVE_SYS_ATTR_H
|
|
|
|
#include <sys/attr.h>
|
|
|
|
#endif
|
|
|
|
|
2016-06-20 14:00:17 +03:00
|
|
|
#define USE_NAME_ON_FS_REAL_BASENAME 1 /* platform dependent APIs to
|
|
|
|
* get real basenames */
|
|
|
|
#define USE_NAME_ON_FS_BY_FNMATCH 2 /* select the matching
|
|
|
|
* basename by fnmatch */
|
|
|
|
|
2014-12-25 09:36:18 +03:00
|
|
|
#ifdef HAVE_GETATTRLIST
|
2016-06-20 14:00:17 +03:00
|
|
|
# define USE_NAME_ON_FS USE_NAME_ON_FS_REAL_BASENAME
|
2015-01-07 12:52:53 +03:00
|
|
|
# define RUP32(size) ((size)+3/4)
|
|
|
|
# define SIZEUP32(type) RUP32(sizeof(type))
|
2015-02-03 08:04:49 +03:00
|
|
|
#elif defined _WIN32
|
2016-06-20 14:00:17 +03:00
|
|
|
# define USE_NAME_ON_FS USE_NAME_ON_FS_REAL_BASENAME
|
2015-02-03 08:04:49 +03:00
|
|
|
#elif defined DOSISH
|
2016-06-20 14:00:17 +03:00
|
|
|
# define USE_NAME_ON_FS USE_NAME_ON_FS_BY_FNMATCH
|
2014-12-25 09:36:18 +03:00
|
|
|
#else
|
|
|
|
# define USE_NAME_ON_FS 0
|
|
|
|
#endif
|
|
|
|
|
2013-03-19 12:06:53 +04:00
|
|
|
#ifdef __APPLE__
|
2015-01-07 12:52:53 +03:00
|
|
|
# define NORMALIZE_UTF8PATH 1
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <sys/param.h>
|
|
|
|
# include <sys/mount.h>
|
|
|
|
# include <sys/vnode.h>
|
2013-03-19 12:06:53 +04:00
|
|
|
#else
|
2015-01-07 12:52:53 +03:00
|
|
|
# define NORMALIZE_UTF8PATH 0
|
2013-03-19 12:06:53 +04:00
|
|
|
#endif
|
2015-01-07 13:29:49 +03:00
|
|
|
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "encindex.h"
|
|
|
|
#include "id.h"
|
|
|
|
#include "internal.h"
|
2020-08-14 08:45:23 +03:00
|
|
|
#include "internal/array.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal/dir.h"
|
|
|
|
#include "internal/encoding.h"
|
|
|
|
#include "internal/error.h"
|
|
|
|
#include "internal/file.h"
|
|
|
|
#include "internal/gc.h"
|
|
|
|
#include "internal/io.h"
|
2021-11-18 15:47:18 +03:00
|
|
|
#include "internal/object.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal/vm.h"
|
|
|
|
#include "ruby/encoding.h"
|
|
|
|
#include "ruby/ruby.h"
|
|
|
|
#include "ruby/thread.h"
|
|
|
|
#include "ruby/util.h"
|
2020-01-18 07:59:21 +03:00
|
|
|
#include "builtin.h"
|
2013-03-19 12:06:53 +04:00
|
|
|
|
2019-12-04 11:16:30 +03:00
|
|
|
#ifndef AT_FDCWD
|
|
|
|
# define AT_FDCWD -1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define vm_initialized rb_cThread
|
|
|
|
|
|
|
|
/* define system APIs */
|
|
|
|
#ifdef _WIN32
|
|
|
|
# undef chdir
|
|
|
|
# define chdir(p) rb_w32_uchdir(p)
|
|
|
|
# undef mkdir
|
|
|
|
# define mkdir(p, m) rb_w32_umkdir((p), (m))
|
|
|
|
# undef rmdir
|
|
|
|
# define rmdir(p) rb_w32_urmdir(p)
|
|
|
|
# undef opendir
|
|
|
|
# define opendir(p) rb_w32_uopendir(p)
|
|
|
|
# define ruby_getcwd() rb_w32_ugetcwd(NULL, 0)
|
|
|
|
# define IS_WIN32 1
|
|
|
|
#else
|
|
|
|
# define IS_WIN32 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if NORMALIZE_UTF8PATH
|
2015-04-10 17:57:47 +03:00
|
|
|
# if defined HAVE_FGETATTRLIST || !defined HAVE_GETATTRLIST
|
|
|
|
# define need_normalization(dirp, path) need_normalization(dirp)
|
|
|
|
# else
|
|
|
|
# define need_normalization(dirp, path) need_normalization(path)
|
|
|
|
# endif
|
2015-01-07 12:52:03 +03:00
|
|
|
static inline int
|
2015-04-10 17:57:47 +03:00
|
|
|
need_normalization(DIR *dirp, const char *path)
|
2015-01-07 12:52:03 +03:00
|
|
|
{
|
2015-04-10 17:57:47 +03:00
|
|
|
# if defined HAVE_FGETATTRLIST || defined HAVE_GETATTRLIST
|
2015-01-07 12:52:53 +03:00
|
|
|
u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
|
|
|
|
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
|
2015-04-10 17:57:47 +03:00
|
|
|
# if defined HAVE_FGETATTRLIST
|
|
|
|
int ret = fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), 0);
|
|
|
|
# else
|
|
|
|
int ret = getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0);
|
|
|
|
# endif
|
|
|
|
if (!ret) {
|
2015-01-07 12:52:53 +03:00
|
|
|
const fsobj_tag_t *tag = (void *)(attrbuf+1);
|
|
|
|
switch (*tag) {
|
|
|
|
case VT_HFS:
|
|
|
|
case VT_CIFS:
|
|
|
|
return TRUE;
|
|
|
|
}
|
2015-01-07 12:52:03 +03:00
|
|
|
}
|
2015-01-07 12:52:53 +03:00
|
|
|
# endif
|
2015-01-07 12:52:03 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2013-03-19 12:06:53 +04:00
|
|
|
static inline int
|
|
|
|
has_nonascii(const char *ptr, size_t len)
|
|
|
|
{
|
|
|
|
while (len > 0) {
|
|
|
|
if (!ISASCII(*ptr)) return 1;
|
|
|
|
ptr++;
|
|
|
|
--len;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-01-07 12:52:53 +03:00
|
|
|
# define IF_NORMALIZE_UTF8PATH(something) something
|
2013-03-19 12:06:53 +04:00
|
|
|
#else
|
2015-01-07 12:52:53 +03:00
|
|
|
# define IF_NORMALIZE_UTF8PATH(something) /* nothing */
|
2013-03-19 12:06:53 +04:00
|
|
|
#endif
|
|
|
|
|
2022-02-25 14:08:31 +03:00
|
|
|
#if defined(IFTODT) && defined(DT_UNKNOWN)
|
|
|
|
# define EMULATE_IFTODT 0
|
|
|
|
#else
|
|
|
|
# define EMULATE_IFTODT 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EMULATE_IFTODT
|
2018-09-21 13:31:11 +03:00
|
|
|
# define IFTODT(m) (((m) & S_IFMT) / ((~S_IFMT & (S_IFMT-1)) + 1))
|
2015-07-02 10:15:09 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef enum {
|
2022-02-25 14:08:31 +03:00
|
|
|
#if !EMULATE_IFTODT
|
2015-07-02 10:15:09 +03:00
|
|
|
path_exist = DT_UNKNOWN,
|
|
|
|
path_directory = DT_DIR,
|
|
|
|
path_regular = DT_REG,
|
|
|
|
path_symlink = DT_LNK,
|
|
|
|
#else
|
|
|
|
path_exist,
|
|
|
|
path_directory = IFTODT(S_IFDIR),
|
|
|
|
path_regular = IFTODT(S_IFREG),
|
|
|
|
path_symlink = IFTODT(S_IFLNK),
|
|
|
|
#endif
|
|
|
|
path_noent = -1,
|
|
|
|
path_unknown = -2
|
|
|
|
} rb_pathtype_t;
|
|
|
|
|
1999-10-21 11:52:15 +04:00
|
|
|
#define FNM_NOESCAPE 0x01
|
|
|
|
#define FNM_PATHNAME 0x02
|
2002-03-13 13:11:09 +03:00
|
|
|
#define FNM_DOTMATCH 0x04
|
2001-06-13 14:51:39 +04:00
|
|
|
#define FNM_CASEFOLD 0x08
|
2012-11-04 05:19:11 +04:00
|
|
|
#define FNM_EXTGLOB 0x10
|
2005-12-14 17:40:14 +03:00
|
|
|
#if CASEFOLD_FILESYSTEM
|
|
|
|
#define FNM_SYSCASE FNM_CASEFOLD
|
|
|
|
#else
|
|
|
|
#define FNM_SYSCASE 0
|
|
|
|
#endif
|
2021-04-29 15:31:05 +03:00
|
|
|
#ifdef _WIN32
|
2015-06-04 01:12:24 +03:00
|
|
|
#define FNM_SHORTNAME 0x20
|
|
|
|
#else
|
|
|
|
#define FNM_SHORTNAME 0
|
|
|
|
#endif
|
2020-01-17 18:21:11 +03:00
|
|
|
#define FNM_GLOB_NOSORT 0x40
|
2021-01-12 12:17:02 +03:00
|
|
|
#define FNM_GLOB_SKIPDOT 0x80
|
1999-10-21 11:52:15 +04:00
|
|
|
|
|
|
|
#define FNM_NOMATCH 1
|
|
|
|
#define FNM_ERROR 2
|
|
|
|
|
2010-12-08 14:38:29 +03:00
|
|
|
# define Next(p, e, enc) ((p)+ rb_enc_mbclen((p), (e), (enc)))
|
|
|
|
# define Inc(p, e, enc) ((p) = Next((p), (e), (enc)))
|
2004-01-02 19:21:26 +03:00
|
|
|
|
2004-03-12 18:00:39 +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
|
|
|
bracket(
|
|
|
|
const char *p, /* pattern (next to '[') */
|
2009-04-12 14:54:59 +04:00
|
|
|
const char *pend,
|
* 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
|
|
|
const char *s, /* string */
|
2009-04-12 14:54:59 +04:00
|
|
|
const char *send,
|
2008-07-07 21:29:44 +04:00
|
|
|
int flags,
|
|
|
|
rb_encoding *enc)
|
1999-10-21 11:52:15 +04:00
|
|
|
{
|
2004-03-08 09:10:22 +03:00
|
|
|
const int nocase = flags & FNM_CASEFOLD;
|
|
|
|
const int escape = !(flags & FNM_NOESCAPE);
|
2009-04-12 14:54:59 +04:00
|
|
|
unsigned int c1, c2;
|
|
|
|
int r;
|
2004-03-12 18:00:39 +03:00
|
|
|
int ok = 0, not = 0;
|
|
|
|
|
2010-09-20 18:23:16 +04:00
|
|
|
if (p >= pend) return NULL;
|
2004-03-08 09:10:22 +03:00
|
|
|
if (*p == '!' || *p == '^') {
|
|
|
|
not = 1;
|
|
|
|
p++;
|
|
|
|
}
|
1999-10-21 11:52:15 +04:00
|
|
|
|
2004-03-12 18:00:39 +03:00
|
|
|
while (*p != ']') {
|
|
|
|
const char *t1 = p;
|
2004-03-08 09:10:22 +03:00
|
|
|
if (escape && *t1 == '\\')
|
|
|
|
t1++;
|
|
|
|
if (!*t1)
|
2004-07-17 22:20:57 +04:00
|
|
|
return NULL;
|
2009-04-16 19:48:25 +04:00
|
|
|
p = t1 + (r = rb_enc_mbclen(t1, pend, enc));
|
2010-09-20 18:23:16 +04:00
|
|
|
if (p >= pend) return NULL;
|
2004-03-12 18:00:39 +03:00
|
|
|
if (p[0] == '-' && p[1] != ']') {
|
|
|
|
const char *t2 = p + 1;
|
2009-04-12 14:54:59 +04:00
|
|
|
int r2;
|
2004-03-08 09:10:22 +03:00
|
|
|
if (escape && *t2 == '\\')
|
|
|
|
t2++;
|
|
|
|
if (!*t2)
|
2004-07-17 22:20:57 +04:00
|
|
|
return NULL;
|
2009-04-12 14:54:59 +04:00
|
|
|
p = t2 + (r2 = rb_enc_mbclen(t2, pend, enc));
|
|
|
|
if (ok) continue;
|
|
|
|
if ((r <= (send-s) && memcmp(t1, s, r) == 0) ||
|
2013-05-25 13:32:47 +04:00
|
|
|
(r2 <= (send-s) && memcmp(t2, s, r2) == 0)) {
|
2004-03-08 09:10:22 +03:00
|
|
|
ok = 1;
|
2009-04-12 14:54:59 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
c1 = rb_enc_codepoint(s, send, enc);
|
|
|
|
if (nocase) c1 = rb_enc_toupper(c1, enc);
|
|
|
|
c2 = rb_enc_codepoint(t1, pend, enc);
|
|
|
|
if (nocase) c2 = rb_enc_toupper(c2, enc);
|
|
|
|
if (c1 < c2) continue;
|
|
|
|
c2 = rb_enc_codepoint(t2, pend, enc);
|
|
|
|
if (nocase) c2 = rb_enc_toupper(c2, enc);
|
|
|
|
if (c1 > c2) continue;
|
2004-03-08 09:10:22 +03:00
|
|
|
}
|
2009-04-12 14:54:59 +04:00
|
|
|
else {
|
|
|
|
if (ok) continue;
|
2009-04-14 13:11:29 +04:00
|
|
|
if (r <= (send-s) && memcmp(t1, s, r) == 0) {
|
|
|
|
ok = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2009-04-12 14:54:59 +04:00
|
|
|
if (!nocase) continue;
|
|
|
|
c1 = rb_enc_toupper(rb_enc_codepoint(s, send, enc), enc);
|
|
|
|
c2 = rb_enc_toupper(rb_enc_codepoint(p, pend, enc), enc);
|
|
|
|
if (c1 != c2) continue;
|
|
|
|
}
|
|
|
|
ok = 1;
|
1999-10-21 11:52:15 +04:00
|
|
|
}
|
2004-03-08 09:10:22 +03:00
|
|
|
|
2004-07-17 22:20:57 +04:00
|
|
|
return ok == not ? NULL : (char *)p + 1;
|
1999-10-21 11:52:15 +04:00
|
|
|
}
|
|
|
|
|
2015-12-14 05:51:13 +03:00
|
|
|
/* If FNM_PATHNAME is set, only path element will be matched. (up to '/' or '\0')
|
2004-03-12 18:00:39 +03:00
|
|
|
Otherwise, entire string will be matched.
|
|
|
|
End marker itself won't be compared.
|
|
|
|
And if function succeeds, *pcur reaches end marker.
|
|
|
|
*/
|
2004-04-09 12:06:01 +04:00
|
|
|
#define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p))
|
2004-03-16 05:24:47 +03:00
|
|
|
#define ISEND(p) (!*(p) || (pathname && *(p) == '/'))
|
2004-03-12 18:00:39 +03:00
|
|
|
#define RETURN(val) return *pcur = p, *scur = s, (val);
|
|
|
|
|
1999-10-21 11:52:15 +04:00
|
|
|
static 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
|
|
|
fnmatch_helper(
|
|
|
|
const char **pcur, /* pattern */
|
|
|
|
const char **scur, /* string */
|
2008-07-07 21:29:44 +04:00
|
|
|
int flags,
|
|
|
|
rb_encoding *enc)
|
1999-10-21 11:52:15 +04:00
|
|
|
{
|
2004-03-12 18:00:39 +03:00
|
|
|
const int period = !(flags & FNM_DOTMATCH);
|
2004-03-16 05:24:47 +03:00
|
|
|
const int pathname = flags & FNM_PATHNAME;
|
2004-03-12 18:00:39 +03:00
|
|
|
const int escape = !(flags & FNM_NOESCAPE);
|
|
|
|
const int nocase = flags & FNM_CASEFOLD;
|
1999-10-21 11:52:15 +04:00
|
|
|
|
2004-03-12 18:00:39 +03:00
|
|
|
const char *ptmp = 0;
|
|
|
|
const char *stmp = 0;
|
2004-01-07 16:28:15 +03:00
|
|
|
|
2004-03-12 18:00:39 +03:00
|
|
|
const char *p = *pcur;
|
2008-07-08 03:00:58 +04:00
|
|
|
const char *pend = p + strlen(p);
|
2004-03-12 18:00:39 +03:00
|
|
|
const char *s = *scur;
|
2008-07-08 03:00:58 +04:00
|
|
|
const char *send = s + strlen(s);
|
1999-10-21 11:52:15 +04:00
|
|
|
|
2009-04-12 14:54:59 +04:00
|
|
|
int r;
|
|
|
|
|
2017-10-27 11:40:40 +03:00
|
|
|
if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
|
|
|
|
RETURN(FNM_NOMATCH);
|
1999-10-21 11:52:15 +04:00
|
|
|
|
2004-03-12 18:00:39 +03:00
|
|
|
while (1) {
|
2004-03-16 05:24:47 +03:00
|
|
|
switch (*p) {
|
|
|
|
case '*':
|
2004-03-12 18:00:39 +03:00
|
|
|
do { p++; } while (*p == '*');
|
2004-03-16 05:24:47 +03:00
|
|
|
if (ISEND(UNESCAPE(p))) {
|
|
|
|
p = UNESCAPE(p);
|
2004-03-12 18:00:39 +03:00
|
|
|
RETURN(0);
|
2004-03-16 05:24:47 +03:00
|
|
|
}
|
|
|
|
if (ISEND(s))
|
|
|
|
RETURN(FNM_NOMATCH);
|
2004-03-12 18:00:39 +03:00
|
|
|
ptmp = p;
|
|
|
|
stmp = s;
|
2004-03-16 05:24:47 +03:00
|
|
|
continue;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2004-03-12 18:00:39 +03:00
|
|
|
case '?':
|
2004-03-16 05:24:47 +03:00
|
|
|
if (ISEND(s))
|
|
|
|
RETURN(FNM_NOMATCH);
|
2004-03-12 18:00:39 +03:00
|
|
|
p++;
|
2008-07-08 03:00:58 +04:00
|
|
|
Inc(s, send, enc);
|
2004-03-12 18:00:39 +03:00
|
|
|
continue;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2004-03-12 18:00:39 +03:00
|
|
|
case '[': {
|
2004-03-16 05:24:47 +03:00
|
|
|
const char *t;
|
|
|
|
if (ISEND(s))
|
|
|
|
RETURN(FNM_NOMATCH);
|
2009-04-12 14:54:59 +04:00
|
|
|
if ((t = bracket(p + 1, pend, s, send, flags, enc)) != 0) {
|
2004-03-12 18:00:39 +03:00
|
|
|
p = t;
|
2008-07-08 03:00:58 +04:00
|
|
|
Inc(s, send, enc);
|
2004-03-12 18:00:39 +03:00
|
|
|
continue;
|
1999-10-21 11:52:15 +04:00
|
|
|
}
|
2004-03-12 18:00:39 +03:00
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2004-03-12 18:00:39 +03:00
|
|
|
/* ordinary */
|
2004-03-16 05:24:47 +03:00
|
|
|
p = UNESCAPE(p);
|
|
|
|
if (ISEND(s))
|
|
|
|
RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
|
|
|
|
if (ISEND(p))
|
|
|
|
goto failed;
|
2009-04-15 07:00:31 +04:00
|
|
|
r = rb_enc_precise_mbclen(p, pend, enc);
|
|
|
|
if (!MBCLEN_CHARFOUND_P(r))
|
|
|
|
goto failed;
|
2009-04-12 14:54:59 +04:00
|
|
|
if (r <= (send-s) && memcmp(p, s, r) == 0) {
|
|
|
|
p += r;
|
|
|
|
s += r;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!nocase) goto failed;
|
|
|
|
if (rb_enc_toupper(rb_enc_codepoint(p, pend, enc), enc) !=
|
|
|
|
rb_enc_toupper(rb_enc_codepoint(s, send, enc), enc))
|
2004-03-12 18:00:39 +03:00
|
|
|
goto failed;
|
2009-04-12 14:54:59 +04:00
|
|
|
p += r;
|
2008-07-08 03:00:58 +04:00
|
|
|
Inc(s, send, enc);
|
2004-03-12 18:00:39 +03:00
|
|
|
continue;
|
|
|
|
|
|
|
|
failed: /* try next '*' position */
|
|
|
|
if (ptmp && stmp) {
|
|
|
|
p = ptmp;
|
2008-07-08 03:00:58 +04:00
|
|
|
Inc(stmp, send, enc); /* !ISEND(*stmp) */
|
2004-03-12 18:00:39 +03:00
|
|
|
s = stmp;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
RETURN(FNM_NOMATCH);
|
1999-10-21 11:52:15 +04:00
|
|
|
}
|
2004-03-12 18:00:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static 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
|
|
|
fnmatch(
|
2008-07-08 06:44:12 +04:00
|
|
|
const char *pattern,
|
|
|
|
rb_encoding *enc,
|
|
|
|
const char *string,
|
* 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
|
|
|
int flags)
|
2004-03-12 18:00:39 +03:00
|
|
|
{
|
2008-07-08 06:44:12 +04:00
|
|
|
const char *p = pattern;
|
|
|
|
const char *s = string;
|
|
|
|
const char *send = s + strlen(string);
|
2004-03-12 18:00:39 +03:00
|
|
|
const int period = !(flags & FNM_DOTMATCH);
|
|
|
|
const int pathname = flags & FNM_PATHNAME;
|
|
|
|
|
|
|
|
const char *ptmp = 0;
|
|
|
|
const char *stmp = 0;
|
|
|
|
|
|
|
|
if (pathname) {
|
|
|
|
while (1) {
|
|
|
|
if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
|
|
|
|
do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
|
|
|
|
ptmp = p;
|
|
|
|
stmp = s;
|
|
|
|
}
|
2008-07-07 21:29:44 +04:00
|
|
|
if (fnmatch_helper(&p, &s, flags, enc) == 0) {
|
2008-07-08 03:00:58 +04:00
|
|
|
while (*s && *s != '/') Inc(s, send, enc);
|
2004-03-12 18:00:39 +03:00
|
|
|
if (*p && *s) {
|
|
|
|
p++;
|
|
|
|
s++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!*p && !*s)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* failed : try next recursion */
|
2004-03-16 05:24:47 +03:00
|
|
|
if (ptmp && stmp && !(period && *stmp == '.')) {
|
2008-07-08 03:00:58 +04:00
|
|
|
while (*stmp && *stmp != '/') Inc(stmp, send, enc);
|
2004-03-12 18:00:39 +03:00
|
|
|
if (*stmp) {
|
|
|
|
p = ptmp;
|
|
|
|
stmp++;
|
|
|
|
s = stmp;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FNM_NOMATCH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2008-07-07 21:29:44 +04:00
|
|
|
return fnmatch_helper(&p, &s, flags, enc);
|
1999-10-21 11:52:15 +04:00
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE rb_cDir;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data {
|
|
|
|
DIR *dir;
|
2017-06-01 18:18:51 +03:00
|
|
|
const VALUE path;
|
2008-09-08 17:32:53 +04:00
|
|
|
rb_encoding *enc;
|
2001-09-19 10:54:11 +04:00
|
|
|
};
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static void
|
2009-09-09 06:28:21 +04:00
|
|
|
dir_free(void *ptr)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-09-09 06:28:21 +04:00
|
|
|
struct dir_data *dir = ptr;
|
2017-03-17 22:59:56 +03:00
|
|
|
|
|
|
|
if (dir->dir) closedir(dir->dir);
|
2009-09-09 06:28:21 +04:00
|
|
|
}
|
|
|
|
|
2023-11-26 13:09:16 +03:00
|
|
|
RUBY_REFERENCES(dir_refs) = {
|
2023-11-26 10:04:27 +03:00
|
|
|
RUBY_REF_EDGE(struct dir_data, path),
|
2023-11-26 13:09:16 +03:00
|
|
|
RUBY_REF_END
|
|
|
|
};
|
2023-03-17 01:26:08 +03:00
|
|
|
|
2009-09-09 06:28:21 +04:00
|
|
|
static const rb_data_type_t dir_data_type = {
|
|
|
|
"dir",
|
2023-11-21 21:31:05 +03:00
|
|
|
{
|
2023-11-26 10:04:27 +03:00
|
|
|
RUBY_REFS_LIST_PTR(dir_refs),
|
2023-11-21 21:31:05 +03:00
|
|
|
dir_free,
|
|
|
|
NULL, // Nothing allocated externally, so don't need a memsize function
|
|
|
|
},
|
|
|
|
0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
|
2009-09-09 06:28:21 +04:00
|
|
|
};
|
|
|
|
|
* 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
|
|
|
static VALUE dir_close(VALUE);
|
1999-01-20 07:59:39 +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
|
|
|
dir_s_alloc(VALUE klass)
|
2000-02-29 11:05:32 +03:00
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dirp;
|
2009-09-09 06:28:21 +04:00
|
|
|
VALUE obj = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dirp);
|
2000-02-29 11:05:32 +03:00
|
|
|
|
2001-09-19 10:54:11 +04:00
|
|
|
dirp->dir = NULL;
|
2017-06-01 18:18:51 +03:00
|
|
|
RB_OBJ_WRITE(obj, &dirp->path, Qnil);
|
2008-09-08 17:32:53 +04:00
|
|
|
dirp->enc = NULL;
|
2000-02-29 11:05:32 +03:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2017-11-18 05:01:44 +03:00
|
|
|
static void *
|
|
|
|
nogvl_opendir(void *ptr)
|
|
|
|
{
|
|
|
|
const char *path = ptr;
|
|
|
|
|
|
|
|
return (void *)opendir(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
static DIR *
|
|
|
|
opendir_without_gvl(const char *path)
|
|
|
|
{
|
2017-11-18 11:25:29 +03:00
|
|
|
if (vm_initialized) {
|
2017-11-21 15:29:51 +03:00
|
|
|
union { const void *in; void *out; } u;
|
2017-11-18 05:01:44 +03:00
|
|
|
|
2017-11-18 11:25:29 +03:00
|
|
|
u.in = path;
|
2017-11-18 05:01:44 +03:00
|
|
|
|
2024-01-24 14:51:50 +03:00
|
|
|
return IO_WITHOUT_GVL(nogvl_opendir, u.out);
|
2017-11-18 11:25:29 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return opendir(path);
|
2017-11-18 05:01:44 +03:00
|
|
|
}
|
|
|
|
|
2000-02-29 11:05:32 +03:00
|
|
|
static VALUE
|
2020-01-18 07:59:21 +03:00
|
|
|
dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dp;
|
2020-01-18 07:59:21 +03:00
|
|
|
VALUE orig;
|
2015-01-07 13:18:45 +03:00
|
|
|
const char *path;
|
2020-01-18 07:59:21 +03:00
|
|
|
rb_encoding *fsenc = NIL_P(enc) ? rb_filesystem_encoding() : rb_to_encoding(enc);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2018-03-28 12:58:52 +03:00
|
|
|
FilePathValue(dirname);
|
2012-02-25 02:53:42 +04:00
|
|
|
orig = rb_str_dup_frozen(dirname);
|
2011-04-28 11:22:18 +04:00
|
|
|
dirname = rb_str_encode_ospath(dirname);
|
2012-02-25 02:53:42 +04:00
|
|
|
dirname = rb_str_dup_frozen(dirname);
|
2008-06-17 02:29:05 +04:00
|
|
|
|
2009-09-09 06:28:21 +04:00
|
|
|
TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dp);
|
2001-09-19 10:54:11 +04:00
|
|
|
if (dp->dir) closedir(dp->dir);
|
|
|
|
dp->dir = NULL;
|
2017-06-01 18:18:51 +03:00
|
|
|
RB_OBJ_WRITE(dir, &dp->path, Qnil);
|
2008-09-08 17:32:53 +04:00
|
|
|
dp->enc = fsenc;
|
2015-01-07 13:18:45 +03:00
|
|
|
path = RSTRING_PTR(dirname);
|
2017-11-18 05:01:44 +03:00
|
|
|
dp->dir = opendir_without_gvl(path);
|
2001-09-19 10:54:11 +04:00
|
|
|
if (dp->dir == NULL) {
|
2016-10-21 10:40:47 +03:00
|
|
|
int e = errno;
|
|
|
|
if (rb_gc_for_fd(e)) {
|
2017-11-18 05:01:44 +03:00
|
|
|
dp->dir = opendir_without_gvl(path);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2015-01-07 13:19:29 +03:00
|
|
|
#ifdef HAVE_GETATTRLIST
|
2016-10-21 10:40:47 +03:00
|
|
|
else if (e == EIO) {
|
2015-01-07 13:19:29 +03:00
|
|
|
u_int32_t attrbuf[1];
|
|
|
|
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0};
|
|
|
|
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) {
|
2017-11-18 05:01:44 +03:00
|
|
|
dp->dir = opendir_without_gvl(path);
|
2015-01-07 13:19:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2001-09-19 10:54:11 +04:00
|
|
|
if (dp->dir == NULL) {
|
2015-01-07 13:18:45 +03:00
|
|
|
RB_GC_GUARD(dirname);
|
2016-10-21 10:40:47 +03:00
|
|
|
rb_syserr_fail_path(e, orig);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
2017-06-01 18:18:51 +03:00
|
|
|
RB_OBJ_WRITE(dir, &dp->path, orig);
|
2000-05-24 08:34:26 +04:00
|
|
|
|
2000-02-29 11:05:32 +03:00
|
|
|
return dir;
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-02-29 11:05:32 +03:00
|
|
|
static VALUE
|
2020-01-18 07:59:21 +03:00
|
|
|
dir_s_open(rb_execution_context_t *ec, VALUE klass, VALUE dirname, VALUE enc)
|
2000-02-29 11:05:32 +03:00
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dp;
|
2009-09-09 06:28:21 +04:00
|
|
|
VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);
|
2000-05-25 09:55:12 +04:00
|
|
|
|
2020-01-18 07:59:21 +03:00
|
|
|
dir_initialize(ec, dir, dirname, enc);
|
2000-05-24 08:34:26 +04:00
|
|
|
|
|
|
|
return dir;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2020-01-18 07:59:21 +03:00
|
|
|
static VALUE
|
|
|
|
dir_s_close(rb_execution_context_t *ec, VALUE klass, VALUE dir)
|
|
|
|
{
|
|
|
|
return dir_close(dir);
|
|
|
|
}
|
|
|
|
|
2023-02-10 00:34:37 +03:00
|
|
|
# if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
|
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.for_fd(fd) -> dir
|
2023-02-10 00:34:37 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Returns a new \Dir object representing the directory specified by the given
|
|
|
|
* integer directory file descriptor +fd+:
|
2023-02-10 00:34:37 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* d0 = Dir.new('..')
|
|
|
|
* d1 = Dir.for_fd(d0.fileno)
|
2023-02-10 00:34:37 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Note that the returned +d1+ does not have an associated path:
|
2023-02-10 00:34:37 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* d0.path # => '..'
|
|
|
|
* d1.path # => nil
|
|
|
|
*
|
|
|
|
* This method uses the
|
|
|
|
* {fdopendir()}[https://www.man7.org/linux/man-pages/man3/fdopendir.3p.html]
|
|
|
|
* function defined by POSIX 2008;
|
|
|
|
* the method is not implemented on non-POSIX platforms (raises NotImplementedError).
|
2023-02-10 00:34:37 +03:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
dir_s_for_fd(VALUE klass, VALUE fd)
|
|
|
|
{
|
|
|
|
struct dir_data *dp;
|
|
|
|
VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);
|
|
|
|
|
|
|
|
if (!(dp->dir = fdopendir(NUM2INT(fd)))) {
|
|
|
|
rb_sys_fail("fdopendir");
|
|
|
|
UNREACHABLE_RETURN(Qnil);
|
|
|
|
}
|
|
|
|
|
|
|
|
RB_OBJ_WRITE(dir, &dp->path, Qnil);
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define dir_s_for_fd rb_f_notimplement
|
|
|
|
#endif
|
|
|
|
|
2018-01-18 12:44:38 +03:00
|
|
|
NORETURN(static void dir_closed(void));
|
|
|
|
|
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
|
|
|
dir_closed(void)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_raise(rb_eIOError, "closed directory");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2009-11-04 02:26:02 +03:00
|
|
|
static struct dir_data *
|
2015-03-23 17:18:30 +03:00
|
|
|
dir_get(VALUE dir)
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
|
|
|
{
|
|
|
|
rb_check_frozen(dir);
|
2015-03-23 17:18:30 +03:00
|
|
|
return rb_check_typeddata(dir, &dir_data_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct dir_data *
|
|
|
|
dir_check(VALUE dir)
|
|
|
|
{
|
|
|
|
struct dir_data *dirp = dir_get(dir);
|
2009-11-04 02:26:02 +03:00
|
|
|
if (!dirp->dir) dir_closed();
|
|
|
|
return dirp;
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
|
|
|
}
|
|
|
|
|
2010-12-08 14:38:29 +03:00
|
|
|
#define GetDIR(obj, dirp) ((dirp) = dir_check(obj))
|
2001-09-19 10:54:11 +04:00
|
|
|
|
2008-06-17 02:29:05 +04:00
|
|
|
|
2004-01-10 16:46:21 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* inspect -> string
|
|
|
|
*
|
|
|
|
* Returns a string description of +self+:
|
|
|
|
*
|
|
|
|
* Dir.new('example').inspect # => "#<Dir:example>"
|
2004-01-10 16:46:21 +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
|
|
|
dir_inspect(VALUE dir)
|
2004-01-10 16:46:21 +03:00
|
|
|
{
|
|
|
|
struct dir_data *dirp;
|
|
|
|
|
2009-09-09 06:28:21 +04:00
|
|
|
TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
|
2008-07-30 17:13:57 +04:00
|
|
|
if (!NIL_P(dirp->path)) {
|
2012-02-25 02:53:51 +04:00
|
|
|
VALUE str = rb_str_new_cstr("#<");
|
|
|
|
rb_str_append(str, rb_class_name(CLASS_OF(dir)));
|
|
|
|
rb_str_cat2(str, ":");
|
|
|
|
rb_str_append(str, dirp->path);
|
|
|
|
rb_str_cat2(str, ">");
|
|
|
|
return str;
|
2004-01-10 16:46:21 +03:00
|
|
|
}
|
2018-01-22 16:09:37 +03:00
|
|
|
return rb_funcallv(dir, idTo_s, 0, 0);
|
2004-01-10 16:46:21 +03:00
|
|
|
}
|
|
|
|
|
2015-11-06 20:07:08 +03:00
|
|
|
/* Workaround for Solaris 10 that does not have dirfd.
|
|
|
|
Note: Solaris 11 (POSIX.1-2008 compliant) has dirfd(3C).
|
|
|
|
*/
|
|
|
|
#if defined(__sun) && !defined(HAVE_DIRFD)
|
|
|
|
# if defined(HAVE_DIR_D_FD)
|
|
|
|
# define dirfd(x) ((x)->d_fd)
|
|
|
|
# define HAVE_DIRFD 1
|
|
|
|
# elif defined(HAVE_DIR_DD_FD)
|
|
|
|
# define dirfd(x) ((x)->dd_fd)
|
|
|
|
# define HAVE_DIRFD 1
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2014-09-04 19:54:04 +04:00
|
|
|
#ifdef HAVE_DIRFD
|
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* fileno -> integer
|
2014-09-04 19:54:04 +04:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Returns the file descriptor used in <em>dir</em>.
|
2014-09-04 19:54:04 +04:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* d = Dir.new('..')
|
|
|
|
* d.fileno # => 8
|
2014-09-04 19:54:04 +04:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* This method uses the
|
|
|
|
* {dirfd()}[https://www.man7.org/linux/man-pages/man3/dirfd.3.html]
|
|
|
|
* function defined by POSIX 2008;
|
|
|
|
* the method is not implemented on non-POSIX platforms (raises NotImplementedError).
|
2014-09-04 19:54:04 +04:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
dir_fileno(VALUE dir)
|
|
|
|
{
|
|
|
|
struct dir_data *dirp;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
GetDIR(dir, dirp);
|
|
|
|
fd = dirfd(dirp->dir);
|
|
|
|
if (fd == -1)
|
|
|
|
rb_sys_fail("dirfd");
|
|
|
|
return INT2NUM(fd);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define dir_fileno rb_f_notimplement
|
|
|
|
#endif
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* path -> string or nil
|
|
|
|
*
|
|
|
|
* Returns the +dirpath+ string that was used to create +self+
|
|
|
|
* (or +nil+ if created by method Dir.for_fd):
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Dir.new('example').path # => "example"
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
|
|
|
*/
|
2001-09-19 10:54: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
|
|
|
dir_path(VALUE dir)
|
2001-09-19 10:54:11 +04:00
|
|
|
{
|
|
|
|
struct dir_data *dirp;
|
|
|
|
|
2009-09-09 06:28:21 +04:00
|
|
|
TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
|
2008-07-30 17:13:57 +04:00
|
|
|
if (NIL_P(dirp->path)) return Qnil;
|
|
|
|
return rb_str_dup(dirp->path);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2013-06-03 02:38:11 +04:00
|
|
|
#if defined _WIN32
|
2015-09-15 09:06:19 +03:00
|
|
|
static int
|
|
|
|
fundamental_encoding_p(rb_encoding *enc)
|
|
|
|
{
|
2015-10-29 08:30:50 +03:00
|
|
|
switch (rb_enc_to_index(enc)) {
|
2022-07-13 12:54:08 +03:00
|
|
|
case ENCINDEX_ASCII_8BIT:
|
2015-09-15 09:06:19 +03:00
|
|
|
case ENCINDEX_US_ASCII:
|
|
|
|
case ENCINDEX_UTF_8:
|
|
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2013-06-03 02:38:11 +04:00
|
|
|
# define READDIR(dir, enc) rb_w32_readdir((dir), (enc))
|
2009-04-21 04:25:43 +04:00
|
|
|
#else
|
2013-06-03 02:38:11 +04:00
|
|
|
# define READDIR(dir, enc) readdir((dir))
|
2009-08-19 20:10:06 +04:00
|
|
|
#endif
|
2017-10-04 03:04:51 +03:00
|
|
|
|
|
|
|
/* safe to use without GVL */
|
2016-02-16 11:34:47 +03:00
|
|
|
static int
|
|
|
|
to_be_skipped(const struct dirent *dp)
|
|
|
|
{
|
|
|
|
const char *name = dp->d_name;
|
|
|
|
if (name[0] != '.') return FALSE;
|
|
|
|
#ifdef HAVE_DIRENT_NAMLEN
|
|
|
|
switch (NAMLEN(dp)) {
|
|
|
|
case 2:
|
|
|
|
if (name[1] != '.') return FALSE;
|
|
|
|
case 1:
|
|
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (!name[1]) return TRUE;
|
|
|
|
if (name[1] != '.') return FALSE;
|
|
|
|
if (!name[2]) return TRUE;
|
|
|
|
#endif
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-08-19 20:10:06 +04:00
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* read -> string or nil
|
|
|
|
*
|
|
|
|
* Reads and returns the next entry name from +self+;
|
|
|
|
* returns +nil+ if at end-of-stream;
|
|
|
|
* see {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like]:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* dir = Dir.new('example')
|
|
|
|
* dir.read # => "."
|
|
|
|
* dir.read # => ".."
|
|
|
|
* dir.read # => "config.h"
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
|
|
|
*/
|
2009-02-06 22:04:44 +03:00
|
|
|
static VALUE
|
|
|
|
dir_read(VALUE dir)
|
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dirp;
|
1999-01-20 07:59:39 +03:00
|
|
|
struct dirent *dp;
|
|
|
|
|
|
|
|
GetDIR(dir, dirp);
|
2023-04-10 04:53:13 +03:00
|
|
|
rb_errno_set(0);
|
2017-11-15 10:24:26 +03:00
|
|
|
if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
|
2008-10-18 14:36:20 +04:00
|
|
|
return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
|
2001-09-19 10:54:11 +04:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
else {
|
2016-10-21 10:40:47 +03:00
|
|
|
int e = errno;
|
|
|
|
if (e != 0) rb_syserr_fail(e, 0);
|
2012-04-15 04:06:13 +04:00
|
|
|
return Qnil; /* end of stream */
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-25 05:50:21 +03:00
|
|
|
static VALUE dir_each_entry(VALUE, VALUE (*)(VALUE, VALUE), VALUE, int);
|
2017-05-25 04:46:36 +03:00
|
|
|
|
|
|
|
static VALUE
|
|
|
|
dir_yield(VALUE arg, VALUE path)
|
|
|
|
{
|
|
|
|
return rb_yield(path);
|
|
|
|
}
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* each {|entry_name| ... } -> self
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Calls the block with each entry name in +self+:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Dir.new('example').each {|entry_name| p entry_name }
|
2010-05-13 09:49:55 +04:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Output:
|
|
|
|
|
|
|
|
* "."
|
|
|
|
* ".."
|
|
|
|
* "config.h"
|
|
|
|
* "lib"
|
|
|
|
* "main.rb"
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* With no block given, returns an Enumerator.
|
2003-12-19 18:18:09 +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
|
|
|
dir_each(VALUE dir)
|
2017-05-25 04:46:36 +03:00
|
|
|
{
|
|
|
|
RETURN_ENUMERATOR(dir, 0, 0);
|
2017-05-25 05:50:21 +03:00
|
|
|
return dir_each_entry(dir, dir_yield, Qnil, FALSE);
|
2017-05-25 04:46:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2017-05-25 05:50:21 +03:00
|
|
|
dir_each_entry(VALUE dir, VALUE (*each)(VALUE, VALUE), VALUE arg, int children_only)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dirp;
|
1998-01-16 15:13:05 +03:00
|
|
|
struct dirent *dp;
|
2015-01-07 12:52:53 +03:00
|
|
|
IF_NORMALIZE_UTF8PATH(int norm_p);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
GetDIR(dir, dirp);
|
2005-07-27 11:27:19 +04:00
|
|
|
rewinddir(dirp->dir);
|
2015-04-10 17:57:47 +03:00
|
|
|
IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp->dir, RSTRING_PTR(dirp->path)));
|
2017-11-15 10:24:26 +03:00
|
|
|
while ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
|
2013-05-20 22:11:23 +04:00
|
|
|
const char *name = dp->d_name;
|
|
|
|
size_t namlen = NAMLEN(dp);
|
|
|
|
VALUE path;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2017-05-25 05:50:21 +03:00
|
|
|
if (children_only && name[0] == '.') {
|
|
|
|
if (namlen == 1) continue; /* current directory */
|
|
|
|
if (namlen == 2 && name[1] == '.') continue; /* parent directory */
|
|
|
|
}
|
2015-01-07 12:52:53 +03:00
|
|
|
#if NORMALIZE_UTF8PATH
|
|
|
|
if (norm_p && has_nonascii(name, namlen) &&
|
2013-08-31 08:30:25 +04:00
|
|
|
!NIL_P(path = rb_str_normalize_ospath(name, namlen))) {
|
|
|
|
path = rb_external_str_with_enc(path, dirp->enc);
|
2013-05-20 22:11:23 +04:00
|
|
|
}
|
2013-08-31 08:30:25 +04:00
|
|
|
else
|
2013-05-20 22:11:23 +04:00
|
|
|
#endif
|
|
|
|
path = rb_external_str_new_with_enc(name, namlen, dirp->enc);
|
2017-05-25 04:46:36 +03:00
|
|
|
(*each)(arg, path);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
2009-04-16 20:58:06 +04:00
|
|
|
#ifdef HAVE_TELLDIR
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* tell -> integer
|
|
|
|
*
|
|
|
|
* Returns the current position of +self+;
|
|
|
|
* see {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like]:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* dir = Dir.new('example')
|
|
|
|
* dir.tell # => 0
|
|
|
|
* dir.read # => "."
|
|
|
|
* dir.tell # => 1
|
2003-12-19 18:18:09 +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
|
|
|
dir_tell(VALUE dir)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dirp;
|
1999-08-13 09:45:20 +04:00
|
|
|
long pos;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-04-06 04:45:02 +04:00
|
|
|
GetDIR(dir, dirp);
|
2001-09-19 10:54:11 +04:00
|
|
|
pos = telldir(dirp->dir);
|
1999-01-20 07:59:39 +03:00
|
|
|
return rb_int2inum(pos);
|
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 dir_tell rb_f_notimplement
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
2009-04-16 20:58:06 +04:00
|
|
|
#ifdef HAVE_SEEKDIR
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* seek(position) -> self
|
|
|
|
*
|
|
|
|
* Sets the position in +self+ and returns +self+.
|
|
|
|
* The value of +position+ should have been returned from an earlier call to #tell;
|
|
|
|
* if not, the return values from subsequent calls to #read are unspecified.
|
|
|
|
*
|
|
|
|
* See {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like].
|
|
|
|
*
|
|
|
|
* Examples:
|
|
|
|
*
|
|
|
|
* dir = Dir.new('example')
|
|
|
|
* dir.pos # => 0
|
|
|
|
* dir.seek(3) # => #<Dir:example>
|
|
|
|
* dir.pos # => 3
|
|
|
|
* dir.seek(30) # => #<Dir:example>
|
|
|
|
* dir.pos # => 5
|
|
|
|
*
|
2003-12-19 18:18:09 +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
|
|
|
dir_seek(VALUE dir, VALUE pos)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dirp;
|
2009-03-11 19:18:10 +03:00
|
|
|
long p = NUM2LONG(pos);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
GetDIR(dir, dirp);
|
2004-11-21 18:33:56 +03:00
|
|
|
seekdir(dirp->dir, p);
|
2002-01-21 10:44:06 +03:00
|
|
|
return dir;
|
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 dir_seek rb_f_notimplement
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
2013-04-26 13:16:14 +04:00
|
|
|
#ifdef HAVE_SEEKDIR
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* pos = position -> integer
|
|
|
|
*
|
|
|
|
* Sets the position in +self+ and returns +position+.
|
|
|
|
* The value of +position+ should have been returned from an earlier call to #tell;
|
|
|
|
* if not, the return values from subsequent calls to #read are unspecified.
|
|
|
|
*
|
|
|
|
* See {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like].
|
|
|
|
*
|
|
|
|
* Examples:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* dir = Dir.new('example')
|
|
|
|
* dir.pos # => 0
|
|
|
|
* dir.pos = 3 # => 3
|
|
|
|
* dir.pos # => 3
|
|
|
|
* dir.pos = 30 # => 30
|
|
|
|
* dir.pos # => 5
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
|
|
|
*/
|
2002-01-21 10:44:06 +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
|
|
|
dir_set_pos(VALUE dir, VALUE pos)
|
2002-01-21 10:44:06 +03:00
|
|
|
{
|
|
|
|
dir_seek(dir, pos);
|
|
|
|
return pos;
|
|
|
|
}
|
2013-04-26 13:16:14 +04:00
|
|
|
#else
|
|
|
|
#define dir_set_pos rb_f_notimplement
|
|
|
|
#endif
|
2002-01-21 10:44:06 +03:00
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* rewind -> self
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Sets the position in +self+ to zero;
|
|
|
|
* see {Dir As Stream-Like}[rdoc-ref:Dir@Dir+As+Stream-Like]:
|
|
|
|
*
|
|
|
|
* dir = Dir.new('example')
|
|
|
|
* dir.read # => "."
|
|
|
|
* dir.read # => ".."
|
|
|
|
* dir.pos # => 2
|
|
|
|
* dir.rewind # => #<Dir:example>
|
|
|
|
* dir.pos # => 0
|
2003-12-19 18:18:09 +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
|
|
|
dir_rewind(VALUE dir)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dirp;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
GetDIR(dir, dirp);
|
2001-09-19 10:54:11 +04:00
|
|
|
rewinddir(dirp->dir);
|
1998-01-16 15:13:05 +03:00
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* close -> nil
|
|
|
|
*
|
|
|
|
* Closes the stream in +self+, if it is open, and returns +nil+;
|
|
|
|
* ignored if +self+ is already closed:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* dir = Dir.new('example')
|
|
|
|
* dir.read # => "."
|
|
|
|
* dir.close # => nil
|
|
|
|
* dir.close # => nil
|
|
|
|
* dir.read # Raises IOError.
|
2003-12-19 18:18:09 +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
|
|
|
dir_close(VALUE dir)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-09-19 10:54:11 +04:00
|
|
|
struct dir_data *dirp;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2015-03-23 17:18:30 +03:00
|
|
|
dirp = dir_get(dir);
|
|
|
|
if (!dirp->dir) return Qnil;
|
2001-09-19 10:54:11 +04:00
|
|
|
closedir(dirp->dir);
|
|
|
|
dirp->dir = NULL;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2017-10-31 02:47:27 +03:00
|
|
|
static void *
|
|
|
|
nogvl_chdir(void *ptr)
|
|
|
|
{
|
|
|
|
const char *path = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)chdir(path);
|
|
|
|
}
|
|
|
|
|
2001-03-16 11:30:09 +03:00
|
|
|
static void
|
2023-02-09 23:45:52 +03:00
|
|
|
dir_chdir0(VALUE path)
|
2001-03-16 11:30:09 +03:00
|
|
|
{
|
2017-12-09 06:46:39 +03:00
|
|
|
if (chdir(RSTRING_PTR(path)) < 0)
|
2012-02-24 11:37:48 +04:00
|
|
|
rb_sys_fail_path(path);
|
2001-03-16 11:30:09 +03:00
|
|
|
}
|
|
|
|
|
2024-02-07 13:43:57 +03:00
|
|
|
static struct {
|
|
|
|
VALUE thread;
|
2024-02-07 13:51:30 +03:00
|
|
|
VALUE path;
|
|
|
|
int line;
|
2024-02-07 13:43:57 +03:00
|
|
|
int blocking;
|
|
|
|
} chdir_lock = {
|
|
|
|
.blocking = 0, .thread = Qnil,
|
2024-02-07 13:51:30 +03:00
|
|
|
.path = Qnil, .line = 0,
|
2024-02-07 13:43:57 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
chdir_enter(void)
|
|
|
|
{
|
2024-02-07 13:51:30 +03:00
|
|
|
if (chdir_lock.blocking == 0) {
|
|
|
|
chdir_lock.path = rb_source_location(&chdir_lock.line);
|
|
|
|
}
|
2024-02-07 13:43:57 +03:00
|
|
|
chdir_lock.blocking++;
|
|
|
|
if (NIL_P(chdir_lock.thread)) {
|
|
|
|
chdir_lock.thread = rb_thread_current();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
chdir_leave(void)
|
|
|
|
{
|
|
|
|
chdir_lock.blocking--;
|
|
|
|
if (chdir_lock.blocking == 0) {
|
|
|
|
chdir_lock.thread = Qnil;
|
2024-02-07 13:51:30 +03:00
|
|
|
chdir_lock.path = Qnil;
|
|
|
|
chdir_lock.line = 0;
|
2024-02-07 13:43:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
chdir_alone_block_p(void)
|
|
|
|
{
|
|
|
|
int block_given = rb_block_given_p();
|
|
|
|
if (chdir_lock.blocking > 0) {
|
|
|
|
if (rb_thread_current() != chdir_lock.thread)
|
|
|
|
rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block");
|
|
|
|
if (!block_given) {
|
2024-02-07 13:51:30 +03:00
|
|
|
if (!NIL_P(chdir_lock.path)) {
|
2024-02-15 04:56:29 +03:00
|
|
|
rb_warn("conflicting chdir during another chdir block\n"
|
|
|
|
"%" PRIsVALUE ":%d: note: previous chdir was here",
|
|
|
|
chdir_lock.path, chdir_lock.line);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_warn("conflicting chdir during another chdir block");
|
2024-02-07 13:51:30 +03:00
|
|
|
}
|
2024-02-07 13:43:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return block_given;
|
|
|
|
}
|
2001-03-16 11:30:09 +03:00
|
|
|
|
2004-09-17 13:24:13 +04:00
|
|
|
struct chdir_data {
|
2004-09-21 07:08:33 +04:00
|
|
|
VALUE old_path, new_path;
|
|
|
|
int done;
|
2023-12-12 04:34:52 +03:00
|
|
|
bool yield_path;
|
2004-09-17 13:24:13 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-26 09:20:15 +03:00
|
|
|
chdir_yield(VALUE v)
|
2004-09-17 13:24:13 +04:00
|
|
|
{
|
2019-08-26 09:20:15 +03:00
|
|
|
struct chdir_data *args = (void *)v;
|
2023-02-09 23:45:52 +03:00
|
|
|
dir_chdir0(args->new_path);
|
2009-07-18 12:05:32 +04:00
|
|
|
args->done = TRUE;
|
2024-02-07 13:43:57 +03:00
|
|
|
chdir_enter();
|
2023-12-12 04:34:52 +03:00
|
|
|
return args->yield_path ? rb_yield(args->new_path) : rb_yield_values2(0, NULL);
|
2004-09-17 13:24:13 +04:00
|
|
|
}
|
|
|
|
|
2001-03-16 11:30:09 +03:00
|
|
|
static VALUE
|
2019-08-26 09:20:15 +03:00
|
|
|
chdir_restore(VALUE v)
|
2001-03-16 11:30:09 +03:00
|
|
|
{
|
2019-08-26 09:20:15 +03:00
|
|
|
struct chdir_data *args = (void *)v;
|
2004-09-21 07:08:33 +04:00
|
|
|
if (args->done) {
|
2024-02-07 13:43:57 +03:00
|
|
|
chdir_leave();
|
2023-02-09 23:45:52 +03:00
|
|
|
dir_chdir0(args->old_path);
|
2004-09-21 07:08:33 +04:00
|
|
|
}
|
2001-03-16 11:30:09 +03:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2023-12-12 04:34:52 +03:00
|
|
|
static VALUE
|
|
|
|
chdir_path(VALUE path, bool yield_path)
|
|
|
|
{
|
2024-02-07 13:43:57 +03:00
|
|
|
if (chdir_alone_block_p()) {
|
2023-12-12 04:34:52 +03:00
|
|
|
struct chdir_data args;
|
|
|
|
|
|
|
|
args.old_path = rb_str_encode_ospath(rb_dir_getwd());
|
|
|
|
args.new_path = path;
|
|
|
|
args.done = FALSE;
|
|
|
|
args.yield_path = yield_path;
|
|
|
|
return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char *p = RSTRING_PTR(path);
|
2024-01-24 14:51:50 +03:00
|
|
|
int r = IO_WITHOUT_GVL_INT(nogvl_chdir, p);
|
2023-12-12 04:34:52 +03:00
|
|
|
if (r < 0)
|
|
|
|
rb_sys_fail_path(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.chdir(new_dirpath) -> 0
|
|
|
|
* Dir.chdir -> 0
|
|
|
|
* Dir.chdir(new_dirpath) {|new_dirpath| ... } -> object
|
|
|
|
* Dir.chdir {|cur_dirpath| ... } -> object
|
|
|
|
*
|
|
|
|
* Changes the current working directory.
|
|
|
|
*
|
|
|
|
* With argument +new_dirpath+ and no block,
|
|
|
|
* changes to the given +dirpath+:
|
|
|
|
*
|
|
|
|
* Dir.pwd # => "/example"
|
|
|
|
* Dir.chdir('..') # => 0
|
|
|
|
* Dir.pwd # => "/"
|
|
|
|
*
|
|
|
|
* With no argument and no block:
|
|
|
|
*
|
|
|
|
* - Changes to the value of environment variable +HOME+ if defined.
|
|
|
|
* - Otherwise changes to the value of environment variable +LOGDIR+ if defined.
|
|
|
|
* - Otherwise makes no change.
|
|
|
|
*
|
|
|
|
* With argument +new_dirpath+ and a block, temporarily changes the working directory:
|
|
|
|
*
|
|
|
|
* - Calls the block with the argument.
|
|
|
|
* - Changes to the given directory.
|
2023-12-12 04:34:52 +03:00
|
|
|
* - Executes the block (yielding the new path).
|
2023-07-05 16:45:54 +03:00
|
|
|
* - Restores the previous working directory.
|
|
|
|
* - Returns the block's return value.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
*
|
|
|
|
* Dir.chdir('/var/spool/mail')
|
|
|
|
* Dir.pwd # => "/var/spool/mail"
|
|
|
|
* Dir.chdir('/tmp') do
|
|
|
|
* Dir.pwd # => "/tmp"
|
|
|
|
* end
|
|
|
|
* Dir.pwd # => "/var/spool/mail"
|
|
|
|
*
|
|
|
|
* With no argument and a block,
|
|
|
|
* calls the block with the current working directory (string)
|
|
|
|
* and returns the block's return value.
|
|
|
|
*
|
|
|
|
* Calls to \Dir.chdir with blocks may be nested:
|
|
|
|
*
|
|
|
|
* Dir.chdir('/var/spool/mail')
|
|
|
|
* Dir.pwd # => "/var/spool/mail"
|
|
|
|
* Dir.chdir('/tmp') do
|
|
|
|
* Dir.pwd # => "/tmp"
|
|
|
|
* Dir.chdir('/usr') do
|
|
|
|
* Dir.pwd # => "/usr"
|
2003-12-19 18:18:09 +03:00
|
|
|
* end
|
2023-07-05 16:45:54 +03:00
|
|
|
* Dir.pwd # => "/tmp"
|
|
|
|
* end
|
|
|
|
* Dir.pwd # => "/var/spool/mail"
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* In a multi-threaded program an error is raised if a thread attempts
|
|
|
|
* to open a +chdir+ block while another thread has one open,
|
|
|
|
* or a call to +chdir+ without a block occurs inside
|
|
|
|
* a block passed to +chdir+ (even in the same thread).
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Raises an exception if the target directory does not exist.
|
2003-12-19 18:18:09 +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
|
|
|
dir_s_chdir(int argc, VALUE *argv, VALUE obj)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-03-16 11:30:09 +03:00
|
|
|
VALUE path = Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2018-12-05 04:09:44 +03:00
|
|
|
if (rb_check_arity(argc, 0, 1) == 1) {
|
|
|
|
path = rb_str_encode_ospath(rb_get_path(argv[0]));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
else {
|
2004-09-21 07:08:33 +04:00
|
|
|
const char *dist = getenv("HOME");
|
1998-01-16 15:13:05 +03:00
|
|
|
if (!dist) {
|
|
|
|
dist = getenv("LOGDIR");
|
2001-09-06 12:48:07 +04:00
|
|
|
if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2004-09-21 07:08:33 +04:00
|
|
|
path = rb_str_new2(dist);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2023-12-12 04:34:52 +03:00
|
|
|
return chdir_path(path, true);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2023-01-17 00:29:43 +03:00
|
|
|
#if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD
|
|
|
|
static void *
|
|
|
|
nogvl_fchdir(void *ptr)
|
|
|
|
{
|
|
|
|
const int *fd = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)fchdir(*fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dir_fchdir(int fd)
|
|
|
|
{
|
|
|
|
if (fchdir(fd) < 0)
|
|
|
|
rb_sys_fail("fchdir");
|
|
|
|
}
|
|
|
|
|
|
|
|
struct fchdir_data {
|
|
|
|
VALUE old_dir;
|
|
|
|
int fd;
|
|
|
|
int done;
|
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
fchdir_yield(VALUE v)
|
|
|
|
{
|
|
|
|
struct fchdir_data *args = (void *)v;
|
|
|
|
dir_fchdir(args->fd);
|
|
|
|
args->done = TRUE;
|
2024-02-07 13:43:57 +03:00
|
|
|
chdir_enter();
|
2023-01-17 00:29:43 +03:00
|
|
|
return rb_yield_values(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
fchdir_restore(VALUE v)
|
|
|
|
{
|
|
|
|
struct fchdir_data *args = (void *)v;
|
|
|
|
if (args->done) {
|
2024-02-07 13:43:57 +03:00
|
|
|
chdir_leave();
|
2023-01-17 00:29:43 +03:00
|
|
|
dir_fchdir(RB_NUM2INT(dir_fileno(args->old_dir)));
|
|
|
|
}
|
|
|
|
dir_close(args->old_dir);
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.fchdir(fd) -> 0
|
|
|
|
* Dir.fchdir(fd) { ... } -> object
|
2023-01-17 00:29:43 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Changes the current working directory to the directory
|
|
|
|
* specified by the integer file descriptor +fd+.
|
2023-01-17 00:29:43 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* When passing a file descriptor over a UNIX socket or to a child process,
|
|
|
|
* using +fchdir+ instead of +chdir+ avoids the
|
|
|
|
* {time-of-check to time-of-use vulnerability}[https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use]
|
|
|
|
*
|
|
|
|
* With no block, changes to the directory given by +fd+:
|
|
|
|
*
|
|
|
|
* Dir.chdir('/var/spool/mail')
|
|
|
|
* Dir.pwd # => "/var/spool/mail"
|
|
|
|
* dir = Dir.new('/usr')
|
|
|
|
* fd = dir.fileno
|
2023-12-15 00:01:48 +03:00
|
|
|
* Dir.fchdir(fd)
|
|
|
|
* Dir.pwd # => "/usr"
|
2023-07-05 16:45:54 +03:00
|
|
|
*
|
|
|
|
* With a block, temporarily changes the working directory:
|
|
|
|
*
|
|
|
|
* - Calls the block with the argument.
|
|
|
|
* - Changes to the given directory.
|
2023-12-12 04:34:52 +03:00
|
|
|
* - Executes the block (yields no args).
|
2023-07-05 16:45:54 +03:00
|
|
|
* - Restores the previous working directory.
|
|
|
|
* - Returns the block's return value.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
*
|
|
|
|
* Dir.chdir('/var/spool/mail')
|
|
|
|
* Dir.pwd # => "/var/spool/mail"
|
2023-12-15 00:01:48 +03:00
|
|
|
* dir = Dir.new('/tmp')
|
|
|
|
* fd = dir.fileno
|
|
|
|
* Dir.fchdir(fd) do
|
2023-07-05 16:45:54 +03:00
|
|
|
* Dir.pwd # => "/tmp"
|
|
|
|
* end
|
|
|
|
* Dir.pwd # => "/var/spool/mail"
|
|
|
|
*
|
|
|
|
* This method uses the
|
|
|
|
* {fchdir()}[https://www.man7.org/linux/man-pages/man3/fchdir.3p.html]
|
|
|
|
* function defined by POSIX 2008;
|
|
|
|
* the method is not implemented on non-POSIX platforms (raises NotImplementedError).
|
|
|
|
*
|
|
|
|
* Raises an exception if the file descriptor is not valid.
|
|
|
|
*
|
|
|
|
* In a multi-threaded program an error is raised if a thread attempts
|
|
|
|
* to open a +chdir+ block while another thread has one open,
|
|
|
|
* or a call to +chdir+ without a block occurs inside
|
|
|
|
* a block passed to +chdir+ (even in the same thread).
|
2023-01-17 00:29:43 +03:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
dir_s_fchdir(VALUE klass, VALUE fd_value)
|
|
|
|
{
|
|
|
|
int fd = RB_NUM2INT(fd_value);
|
|
|
|
|
2024-02-07 13:43:57 +03:00
|
|
|
if (chdir_alone_block_p()) {
|
2023-01-17 00:29:43 +03:00
|
|
|
struct fchdir_data args;
|
|
|
|
args.old_dir = dir_s_alloc(klass);
|
|
|
|
dir_initialize(NULL, args.old_dir, rb_fstring_cstr("."), Qnil);
|
|
|
|
args.fd = fd;
|
|
|
|
args.done = FALSE;
|
|
|
|
return rb_ensure(fchdir_yield, (VALUE)&args, fchdir_restore, (VALUE)&args);
|
|
|
|
}
|
|
|
|
else {
|
2024-01-24 14:51:50 +03:00
|
|
|
int r = IO_WITHOUT_GVL_INT(nogvl_fchdir, &fd);
|
2023-01-17 00:29:43 +03:00
|
|
|
if (r < 0)
|
|
|
|
rb_sys_fail("fchdir");
|
|
|
|
}
|
|
|
|
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define dir_s_fchdir rb_f_notimplement
|
|
|
|
#endif
|
|
|
|
|
2023-02-09 23:45:52 +03:00
|
|
|
/*
|
2023-07-05 16:45:54 +03:00
|
|
|
* call-seq:
|
2023-12-12 04:34:52 +03:00
|
|
|
* chdir -> 0
|
|
|
|
* chdir { ... } -> object
|
2023-07-05 16:45:54 +03:00
|
|
|
*
|
2023-12-12 04:34:52 +03:00
|
|
|
* Changes the current working directory to +self+:
|
2023-02-09 23:45:52 +03:00
|
|
|
*
|
2023-07-05 16:45:54 +03:00
|
|
|
* Dir.pwd # => "/"
|
|
|
|
* dir = Dir.new('example')
|
|
|
|
* dir.chdir
|
2023-12-09 07:54:33 +03:00
|
|
|
* Dir.pwd # => "/example"
|
2023-02-09 23:45:52 +03:00
|
|
|
*
|
2023-12-12 04:34:52 +03:00
|
|
|
* With a block, temporarily changes the working directory:
|
|
|
|
*
|
|
|
|
* - Calls the block.
|
|
|
|
* - Changes to the given directory.
|
|
|
|
* - Executes the block (yields no args).
|
|
|
|
* - Restores the previous working directory.
|
|
|
|
* - Returns the block's return value.
|
|
|
|
*
|
|
|
|
* Uses Dir.fchdir if available, and Dir.chdir if not, see those
|
|
|
|
* methods for caveats.
|
2023-02-09 23:45:52 +03:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
dir_chdir(VALUE dir)
|
|
|
|
{
|
|
|
|
#if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD
|
2023-12-12 04:34:52 +03:00
|
|
|
return dir_s_fchdir(rb_cDir, dir_fileno(dir));
|
2023-02-09 23:45:52 +03:00
|
|
|
#else
|
2023-12-12 04:34:52 +03:00
|
|
|
return chdir_path(dir_get(dir)->path, false);
|
2023-02-09 23:45:52 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-06-12 03:18:30 +03:00
|
|
|
#ifndef _WIN32
|
2010-01-12 03:32:22 +03:00
|
|
|
VALUE
|
2017-06-08 04:58:44 +03:00
|
|
|
rb_dir_getwd_ospath(void)
|
2010-01-12 03:32:22 +03:00
|
|
|
{
|
|
|
|
char *path;
|
|
|
|
VALUE cwd;
|
2017-05-18 14:29:42 +03:00
|
|
|
VALUE path_guard;
|
2010-01-12 03:32:22 +03:00
|
|
|
|
2017-05-18 14:29:42 +03:00
|
|
|
#undef RUBY_UNTYPED_DATA_WARNING
|
|
|
|
#define RUBY_UNTYPED_DATA_WARNING 0
|
|
|
|
path_guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL);
|
2017-11-26 04:36:33 +03:00
|
|
|
path = ruby_getcwd();
|
2017-05-18 14:29:42 +03:00
|
|
|
DATA_PTR(path_guard) = path;
|
2017-06-12 03:18:30 +03:00
|
|
|
#ifdef __APPLE__
|
2015-10-04 04:10:00 +03:00
|
|
|
cwd = rb_str_normalize_ospath(path, strlen(path));
|
|
|
|
#else
|
2019-09-25 06:59:12 +03:00
|
|
|
cwd = rb_str_new2(path);
|
2017-05-16 13:25:56 +03:00
|
|
|
#endif
|
2017-05-18 14:29:42 +03:00
|
|
|
DATA_PTR(path_guard) = 0;
|
2010-01-12 03:32:22 +03:00
|
|
|
|
|
|
|
xfree(path);
|
|
|
|
return cwd;
|
|
|
|
}
|
2017-06-12 03:18:30 +03:00
|
|
|
#endif
|
2010-01-12 03:32:22 +03:00
|
|
|
|
2017-06-08 04:58:44 +03:00
|
|
|
VALUE
|
|
|
|
rb_dir_getwd(void)
|
|
|
|
{
|
|
|
|
rb_encoding *fs = rb_filesystem_encoding();
|
|
|
|
int fsenc = rb_enc_to_index(fs);
|
|
|
|
VALUE cwd = rb_dir_getwd_ospath();
|
|
|
|
|
|
|
|
switch (fsenc) {
|
|
|
|
case ENCINDEX_US_ASCII:
|
2022-07-13 12:54:08 +03:00
|
|
|
fsenc = ENCINDEX_ASCII_8BIT;
|
|
|
|
case ENCINDEX_ASCII_8BIT:
|
2017-06-08 04:58:44 +03:00
|
|
|
break;
|
|
|
|
#if defined _WIN32 || defined __APPLE__
|
|
|
|
default:
|
|
|
|
return rb_str_conv_enc(cwd, NULL, fs);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return rb_enc_associate_index(cwd, fsenc);
|
|
|
|
}
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.pwd -> string
|
|
|
|
*
|
|
|
|
* Returns the path to the current working directory:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.chdir("/tmp") # => 0
|
|
|
|
* Dir.pwd # => "/tmp"
|
2003-12-19 18:18:09 +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
|
|
|
dir_s_getwd(VALUE dir)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2010-01-12 03:32:22 +03:00
|
|
|
return rb_dir_getwd();
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2015-06-23 03:49:26 +03:00
|
|
|
static VALUE
|
|
|
|
check_dirname(VALUE dir)
|
2003-12-15 07:07:03 +03:00
|
|
|
{
|
2015-06-23 03:49:26 +03:00
|
|
|
VALUE d = dir;
|
2003-12-15 07:07:03 +03:00
|
|
|
char *path, *pend;
|
2012-01-25 06:32:06 +04:00
|
|
|
long len;
|
|
|
|
rb_encoding *enc;
|
2003-12-15 07:07:03 +03:00
|
|
|
|
2012-01-21 06:43:48 +04:00
|
|
|
FilePathValue(d);
|
2012-01-25 06:32:06 +04:00
|
|
|
enc = rb_enc_get(d);
|
|
|
|
RSTRING_GETMEM(d, path, len);
|
|
|
|
pend = path + len;
|
|
|
|
pend = rb_enc_path_end(rb_enc_path_skip_prefix(path, pend, enc), pend, enc);
|
|
|
|
if (pend - path < len) {
|
2012-01-21 06:43:48 +04:00
|
|
|
d = rb_str_subseq(d, 0, pend - path);
|
2015-06-30 17:11:56 +03:00
|
|
|
StringValueCStr(d);
|
2003-12-15 07:07:03 +03:00
|
|
|
}
|
2015-06-23 03:49:26 +03:00
|
|
|
return rb_str_encode_ospath(d);
|
2003-12-15 07:07:03 +03:00
|
|
|
}
|
|
|
|
|
2009-06-22 16:23:06 +04:00
|
|
|
#if defined(HAVE_CHROOT)
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.chroot(dirpath) -> 0
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Changes the root directory of the calling process to that specified in +dirpath+.
|
|
|
|
* The new root directory is used for pathnames beginning with <tt>'/'</tt>.
|
|
|
|
* The root directory is inherited by all children of the calling process.
|
|
|
|
*
|
|
|
|
* Only a privileged process may call +chroot+.
|
|
|
|
*
|
|
|
|
* See {Linux chroot}[https://man7.org/linux/man-pages/man2/chroot.2.html].
|
2003-12-19 18:18:09 +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
|
|
|
dir_s_chroot(VALUE dir, VALUE path)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2015-06-23 03:49:26 +03:00
|
|
|
path = check_dirname(path);
|
2006-08-31 14:47:44 +04:00
|
|
|
if (chroot(RSTRING_PTR(path)) == -1)
|
2012-02-24 11:37:48 +04:00
|
|
|
rb_sys_fail_path(path);
|
1998-01-16 15:13:05 +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 dir_s_chroot rb_f_notimplement
|
1998-01-16 15:13:05 +03:00
|
|
|
#endif
|
|
|
|
|
2017-11-01 03:17:11 +03:00
|
|
|
struct mkdir_arg {
|
|
|
|
const char *path;
|
|
|
|
mode_t mode;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *
|
|
|
|
nogvl_mkdir(void *ptr)
|
|
|
|
{
|
|
|
|
struct mkdir_arg *m = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)mkdir(m->path, m->mode);
|
|
|
|
}
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.mkdir(dirpath, permissions = 0775) -> 0
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Creates a directory in the underlying file system
|
|
|
|
* at +dirpath+ with the given +permissions+;
|
|
|
|
* returns zero:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.mkdir('foo')
|
|
|
|
* File.stat(Dir.new('foo')).mode.to_s(8)[1..4] # => "0755"
|
|
|
|
* Dir.mkdir('bar', 0644)
|
|
|
|
* File.stat(Dir.new('bar')).mode.to_s(8)[1..4] # => "0644"
|
2011-01-13 14:58:20 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* See {File Permissions}[rdoc-ref:File@File+Permissions].
|
|
|
|
* Note that argument +permissions+ is ignored on Windows.
|
2003-12-19 18:18:09 +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
|
|
|
dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-11-01 03:17:11 +03:00
|
|
|
struct mkdir_arg m;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE path, vmode;
|
2017-11-01 03:17:11 +03:00
|
|
|
int r;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
|
2017-11-01 03:17:11 +03:00
|
|
|
m.mode = NUM2MODET(vmode);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
else {
|
2017-11-01 03:17:11 +03:00
|
|
|
m.mode = 0777;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2015-06-23 03:49:26 +03:00
|
|
|
path = check_dirname(path);
|
2017-11-01 03:17:11 +03:00
|
|
|
m.path = RSTRING_PTR(path);
|
2024-01-24 14:51:50 +03:00
|
|
|
r = IO_WITHOUT_GVL_INT(nogvl_mkdir, &m);
|
2017-11-01 03:17:11 +03:00
|
|
|
if (r < 0)
|
2012-02-24 11:37:48 +04:00
|
|
|
rb_sys_fail_path(path);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
|
|
|
|
2017-11-01 03:17:11 +03:00
|
|
|
static void *
|
|
|
|
nogvl_rmdir(void *ptr)
|
|
|
|
{
|
|
|
|
const char *path = ptr;
|
|
|
|
|
|
|
|
return (void *)(VALUE)rmdir(path);
|
|
|
|
}
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.rmdir(dirpath) -> 0
|
|
|
|
*
|
|
|
|
* Removes the directory at +dirpath+ from the underlying file system:
|
|
|
|
*
|
|
|
|
* Dir.rmdir('foo') # => 0
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Raises an exception if the directory is not empty.
|
2003-12-19 18:18:09 +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
|
|
|
dir_s_rmdir(VALUE obj, VALUE dir)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2017-11-01 03:17:11 +03:00
|
|
|
const char *p;
|
|
|
|
int r;
|
|
|
|
|
2015-06-23 03:49:26 +03:00
|
|
|
dir = check_dirname(dir);
|
2017-11-01 03:17:11 +03:00
|
|
|
p = RSTRING_PTR(dir);
|
2024-01-24 14:51:50 +03:00
|
|
|
r = IO_WITHOUT_GVL_INT(nogvl_rmdir, (void *)p);
|
2017-11-01 03:17:11 +03:00
|
|
|
if (r < 0)
|
2012-02-24 11:37:48 +04:00
|
|
|
rb_sys_fail_path(dir);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-03-07 11:37:59 +03:00
|
|
|
return INT2FIX(0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2015-02-06 11:37:27 +03:00
|
|
|
struct warning_args {
|
|
|
|
#ifdef RUBY_FUNCTION_NAME_STRING
|
|
|
|
const char *func;
|
|
|
|
#endif
|
|
|
|
const char *mesg;
|
|
|
|
rb_encoding *enc;
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef RUBY_FUNCTION_NAME_STRING
|
|
|
|
#define sys_enc_warning_in(func, mesg, enc) sys_enc_warning(mesg, enc)
|
|
|
|
#endif
|
|
|
|
|
2009-06-09 10:11:10 +04:00
|
|
|
static VALUE
|
|
|
|
sys_warning_1(VALUE mesg)
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
|
|
|
{
|
2015-02-06 11:37:27 +03:00
|
|
|
const struct warning_args *arg = (struct warning_args *)mesg;
|
|
|
|
#ifdef RUBY_FUNCTION_NAME_STRING
|
|
|
|
rb_sys_enc_warning(arg->enc, "%s: %s", arg->func, arg->mesg);
|
|
|
|
#else
|
|
|
|
rb_sys_enc_warning(arg->enc, "%s", arg->mesg);
|
|
|
|
#endif
|
2009-06-09 10:11:10 +04:00
|
|
|
return Qnil;
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-10 01:20:17 +04:00
|
|
|
}
|
|
|
|
|
2015-02-06 11:37:27 +03:00
|
|
|
static void
|
|
|
|
sys_enc_warning_in(const char *func, const char *mesg, rb_encoding *enc)
|
|
|
|
{
|
|
|
|
struct warning_args arg;
|
|
|
|
#ifdef RUBY_FUNCTION_NAME_STRING
|
|
|
|
arg.func = func;
|
|
|
|
#endif
|
|
|
|
arg.mesg = mesg;
|
|
|
|
arg.enc = enc;
|
|
|
|
rb_protect(sys_warning_1, (VALUE)&arg, 0);
|
|
|
|
}
|
|
|
|
|
2009-06-09 10:11:10 +04:00
|
|
|
#define GLOB_VERBOSE (1U << (sizeof(int) * CHAR_BIT - 1))
|
2015-02-06 11:37:27 +03:00
|
|
|
#define sys_warning(val, enc) \
|
|
|
|
((flags & GLOB_VERBOSE) ? sys_enc_warning_in(RUBY_FUNCTION_NAME_STRING, (val), (enc)) :(void)0)
|
2006-10-30 17:23:46 +03:00
|
|
|
|
2020-01-17 18:21:11 +03:00
|
|
|
static inline size_t
|
|
|
|
glob_alloc_size(size_t x, size_t y)
|
2019-10-07 10:56:08 +03:00
|
|
|
{
|
|
|
|
size_t z;
|
|
|
|
if (rb_mul_size_overflow(x, y, SSIZE_MAX, &z)) {
|
|
|
|
rb_memerror(); /* or...? */
|
|
|
|
}
|
|
|
|
else {
|
2020-01-17 18:21:11 +03:00
|
|
|
return z;
|
2019-10-07 10:56:08 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-17 18:21:11 +03:00
|
|
|
static inline void *
|
|
|
|
glob_alloc_n(size_t x, size_t y)
|
|
|
|
{
|
|
|
|
return malloc(glob_alloc_size(x, y));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
glob_realloc_n(void *p, size_t x, size_t y)
|
|
|
|
{
|
|
|
|
return realloc(p, glob_alloc_size(x, y));
|
|
|
|
}
|
|
|
|
|
2010-12-08 14:38:29 +03:00
|
|
|
#define GLOB_ALLOC(type) ((type *)malloc(sizeof(type)))
|
2019-10-07 10:56:08 +03:00
|
|
|
#define GLOB_ALLOC_N(type, n) ((type *)glob_alloc_n(sizeof(type), n))
|
2014-12-25 09:36:18 +03:00
|
|
|
#define GLOB_REALLOC(ptr, size) realloc((ptr), (size))
|
2020-01-17 18:21:11 +03:00
|
|
|
#define GLOB_REALLOC_N(ptr, n) glob_realloc_n(ptr, sizeof(*(ptr)), n)
|
* 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
|
|
|
#define GLOB_FREE(ptr) free(ptr)
|
2010-12-08 14:38:29 +03:00
|
|
|
#define GLOB_JUMP_TAG(status) (((status) == -1) ? rb_memerror() : rb_jump_tag(status))
|
2005-09-14 17:41:02 +04:00
|
|
|
|
2007-04-24 04:33:09 +04:00
|
|
|
/*
|
|
|
|
* ENOTDIR can be returned by stat(2) if a non-leaf element of the path
|
|
|
|
* is not a directory.
|
|
|
|
*/
|
2016-10-31 19:01:30 +03:00
|
|
|
ALWAYS_INLINE(static int to_be_ignored(int e));
|
2016-10-21 10:40:48 +03:00
|
|
|
static inline int
|
|
|
|
to_be_ignored(int e)
|
|
|
|
{
|
|
|
|
return e == ENOENT || e == ENOTDIR;
|
|
|
|
}
|
2007-04-24 04:33:09 +04:00
|
|
|
|
2013-07-03 09:15:28 +04:00
|
|
|
#ifdef _WIN32
|
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
|
|
|
#define STAT(p, s) rb_w32_ustati128((p), (s))
|
2015-03-23 08:40:48 +03:00
|
|
|
#undef lstat
|
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
|
|
|
#define lstat(p, s) rb_w32_ulstati128((p), (s))
|
2013-07-03 09:15:28 +04:00
|
|
|
#else
|
|
|
|
#define STAT(p, s) stat((p), (s))
|
|
|
|
#endif
|
|
|
|
|
2017-03-27 17:57:08 +03:00
|
|
|
typedef int ruby_glob_errfunc(const char*, VALUE, const void*, int);
|
|
|
|
typedef struct {
|
|
|
|
ruby_glob_func *match;
|
|
|
|
ruby_glob_errfunc *error;
|
|
|
|
} ruby_glob_funcs_t;
|
|
|
|
|
2018-07-26 15:48:02 +03:00
|
|
|
static const char *
|
|
|
|
at_subpath(int fd, size_t baselen, const char *path)
|
|
|
|
{
|
|
|
|
#if USE_OPENDIR_AT
|
|
|
|
if (fd != (int)AT_FDCWD && baselen > 0) {
|
|
|
|
path += baselen;
|
|
|
|
if (*path == '/') ++path;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return *path ? path : ".";
|
|
|
|
}
|
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
/* System call with warning */
|
|
|
|
static int
|
2018-07-26 15:48:02 +03:00
|
|
|
do_stat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, rb_encoding *enc)
|
2004-01-29 11:05:29 +03:00
|
|
|
{
|
2017-05-23 17:34:12 +03:00
|
|
|
#if USE_OPENDIR_AT
|
2018-07-26 15:48:02 +03:00
|
|
|
int ret = fstatat(fd, at_subpath(fd, baselen, path), pst, 0);
|
2017-05-23 17:34:12 +03:00
|
|
|
#else
|
2013-07-03 09:15:28 +04:00
|
|
|
int ret = STAT(path, pst);
|
2017-05-23 17:34:12 +03:00
|
|
|
#endif
|
2007-04-24 04:33:09 +04:00
|
|
|
if (ret < 0 && !to_be_ignored(errno))
|
2015-02-06 11:37:27 +03:00
|
|
|
sys_warning(path, enc);
|
2004-02-07 17:22:33 +03:00
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-05-23 17:34:12 +03:00
|
|
|
#if defined HAVE_LSTAT || defined lstat || USE_OPENDIR_AT
|
2004-01-29 11:05:29 +03:00
|
|
|
static int
|
2018-07-26 15:48:02 +03:00
|
|
|
do_lstat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, rb_encoding *enc)
|
2004-01-29 11:05:29 +03:00
|
|
|
{
|
2017-05-23 17:34:12 +03:00
|
|
|
#if USE_OPENDIR_AT
|
2018-07-26 15:48:02 +03:00
|
|
|
int ret = fstatat(fd, at_subpath(fd, baselen, path), pst, AT_SYMLINK_NOFOLLOW);
|
2017-05-23 17:34:12 +03:00
|
|
|
#else
|
2004-01-29 11:05:29 +03:00
|
|
|
int ret = lstat(path, pst);
|
2017-05-23 17:34:12 +03:00
|
|
|
#endif
|
2007-04-24 04:33:09 +04:00
|
|
|
if (ret < 0 && !to_be_ignored(errno))
|
2015-02-06 11:37:27 +03:00
|
|
|
sys_warning(path, enc);
|
2004-02-07 17:22:33 +03:00
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
return ret;
|
|
|
|
}
|
2013-07-03 09:12:03 +04:00
|
|
|
#else
|
|
|
|
#define do_lstat do_stat
|
|
|
|
#endif
|
2004-01-29 11:05:29 +03:00
|
|
|
|
2017-11-18 05:01:49 +03:00
|
|
|
struct opendir_at_arg {
|
|
|
|
int basefd;
|
|
|
|
const char *path;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *
|
|
|
|
with_gvl_gc_for_fd(void *ptr)
|
2004-01-29 11:05:29 +03:00
|
|
|
{
|
2017-11-18 05:01:49 +03:00
|
|
|
int *e = ptr;
|
|
|
|
|
2021-08-31 14:30:35 +03:00
|
|
|
return (void *)RBOOL(rb_gc_for_fd(*e));
|
2017-11-18 05:01:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
gc_for_fd_with_gvl(int e)
|
|
|
|
{
|
2017-11-18 11:25:29 +03:00
|
|
|
if (vm_initialized)
|
|
|
|
return (int)(VALUE)rb_thread_call_with_gvl(with_gvl_gc_for_fd, &e);
|
|
|
|
else
|
2021-08-31 14:30:35 +03:00
|
|
|
return RBOOL(rb_gc_for_fd(e));
|
2017-11-18 05:01:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
nogvl_opendir_at(void *ptr)
|
|
|
|
{
|
|
|
|
const struct opendir_at_arg *oaa = ptr;
|
|
|
|
DIR *dirp;
|
|
|
|
|
2017-05-23 17:34:12 +03:00
|
|
|
#if USE_OPENDIR_AT
|
|
|
|
const int opendir_flags = (O_RDONLY|O_CLOEXEC|
|
2017-11-18 05:01:49 +03:00
|
|
|
# ifdef O_DIRECTORY
|
2017-05-23 17:34:12 +03:00
|
|
|
O_DIRECTORY|
|
2017-11-18 05:01:49 +03:00
|
|
|
# endif /* O_DIRECTORY */
|
2017-05-23 17:34:12 +03:00
|
|
|
0);
|
2018-01-10 04:07:27 +03:00
|
|
|
int fd = openat(oaa->basefd, oaa->path, opendir_flags);
|
2017-11-18 05:01:49 +03:00
|
|
|
|
|
|
|
dirp = fd >= 0 ? fdopendir(fd) : 0;
|
|
|
|
if (!dirp) {
|
|
|
|
int e = errno;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2017-11-18 05:01:49 +03:00
|
|
|
switch (gc_for_fd_with_gvl(e)) {
|
|
|
|
default:
|
2018-01-10 04:07:27 +03:00
|
|
|
if (fd < 0) fd = openat(oaa->basefd, oaa->path, opendir_flags);
|
2017-11-18 05:01:49 +03:00
|
|
|
if (fd >= 0) dirp = fdopendir(fd);
|
|
|
|
if (dirp) return dirp;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2017-11-18 05:01:49 +03:00
|
|
|
e = errno;
|
|
|
|
/* fallthrough*/
|
|
|
|
case 0:
|
|
|
|
if (fd >= 0) close(fd);
|
2023-04-10 04:53:13 +03:00
|
|
|
rb_errno_set(e);
|
2017-11-18 05:01:49 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else /* !USE_OPENDIR_AT */
|
|
|
|
dirp = opendir(oaa->path);
|
|
|
|
if (!dirp && gc_for_fd_with_gvl(errno))
|
|
|
|
dirp = opendir(oaa->path);
|
|
|
|
#endif /* !USE_OPENDIR_AT */
|
|
|
|
|
|
|
|
return dirp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DIR *
|
|
|
|
opendir_at(int basefd, const char *path)
|
|
|
|
{
|
|
|
|
struct opendir_at_arg oaa;
|
|
|
|
|
|
|
|
oaa.basefd = basefd;
|
|
|
|
oaa.path = path;
|
|
|
|
|
2017-11-18 11:25:29 +03:00
|
|
|
if (vm_initialized)
|
2024-01-24 14:51:50 +03:00
|
|
|
return IO_WITHOUT_GVL(nogvl_opendir_at, &oaa);
|
2017-11-18 11:25:29 +03:00
|
|
|
else
|
|
|
|
return nogvl_opendir_at(&oaa);
|
2017-11-18 05:01:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static DIR *
|
2018-07-26 15:48:02 +03:00
|
|
|
do_opendir(const int basefd, size_t baselen, const char *path, int flags, rb_encoding *enc,
|
2017-11-18 05:01:49 +03:00
|
|
|
ruby_glob_errfunc *errfunc, VALUE arg, int *status)
|
|
|
|
{
|
2011-04-28 11:22:18 +04:00
|
|
|
DIR *dirp;
|
|
|
|
#ifdef _WIN32
|
2015-02-03 07:43:52 +03:00
|
|
|
VALUE tmp = 0;
|
2015-09-15 09:06:19 +03:00
|
|
|
if (!fundamental_encoding_p(enc)) {
|
2011-04-28 11:22:18 +04:00
|
|
|
tmp = rb_enc_str_new(path, strlen(path), enc);
|
|
|
|
tmp = rb_str_encode_ospath(tmp);
|
|
|
|
path = RSTRING_PTR(tmp);
|
|
|
|
}
|
|
|
|
#endif
|
2018-07-26 15:48:02 +03:00
|
|
|
dirp = opendir_at(basefd, at_subpath(basefd, baselen, path));
|
2016-10-21 10:44:46 +03:00
|
|
|
if (!dirp) {
|
|
|
|
int e = errno;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2017-11-18 05:01:49 +03:00
|
|
|
*status = 0;
|
|
|
|
if (!to_be_ignored(e)) {
|
2017-03-27 17:57:08 +03:00
|
|
|
if (errfunc) {
|
|
|
|
*status = (*errfunc)(path, arg, enc, e);
|
|
|
|
}
|
2017-11-18 05:01:49 +03:00
|
|
|
else {
|
|
|
|
sys_warning(path, enc);
|
|
|
|
}
|
2016-10-21 10:44:46 +03:00
|
|
|
}
|
|
|
|
}
|
2015-02-03 07:43:52 +03:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (tmp) rb_str_resize(tmp, 0); /* GC guard */
|
|
|
|
#endif
|
2004-02-07 17:22:33 +03:00
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
return dirp;
|
|
|
|
}
|
|
|
|
|
2014-05-16 20:49:25 +04:00
|
|
|
/* Globing pattern */
|
2018-09-22 04:11:40 +03:00
|
|
|
enum glob_pattern_type { PLAIN, ALPHA, BRACE, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
|
2014-05-16 20:49:25 +04:00
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
/* Return nonzero if S has any special globbing chars in it. */
|
2014-05-16 20:49:25 +04:00
|
|
|
static enum glob_pattern_type
|
2010-08-05 11:57:26 +04:00
|
|
|
has_magic(const char *p, const char *pend, int flags, rb_encoding *enc)
|
1999-08-13 09:45:20 +04:00
|
|
|
{
|
2004-04-09 12:06:01 +04:00
|
|
|
const int escape = !(flags & FNM_NOESCAPE);
|
2014-05-16 20:49:25 +04:00
|
|
|
int hasalpha = 0;
|
2018-09-22 04:11:40 +03:00
|
|
|
int hasmagical = 0;
|
2004-04-09 12:06:01 +04:00
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
register char c;
|
|
|
|
|
2010-08-05 11:57:26 +04:00
|
|
|
while (p < pend && (c = *p++) != 0) {
|
1999-08-13 09:45:20 +04:00
|
|
|
switch (c) {
|
2018-09-22 04:11:40 +03:00
|
|
|
case '{':
|
|
|
|
return BRACE;
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
case '*':
|
2004-04-09 12:06:01 +04:00
|
|
|
case '?':
|
|
|
|
case '[':
|
2018-09-22 04:11:40 +03:00
|
|
|
hasmagical = 1;
|
|
|
|
break;
|
1999-08-13 09:45:20 +04:00
|
|
|
|
2004-04-09 12:06:01 +04:00
|
|
|
case '\\':
|
2015-02-07 03:11:00 +03:00
|
|
|
if (escape && p++ >= pend)
|
|
|
|
continue;
|
|
|
|
break;
|
2005-12-14 17:40:14 +03:00
|
|
|
|
2015-02-03 08:04:49 +03:00
|
|
|
#ifdef _WIN32
|
2015-02-07 13:25:27 +03:00
|
|
|
case '.':
|
|
|
|
break;
|
|
|
|
|
2015-02-03 08:04:49 +03:00
|
|
|
case '~':
|
2015-02-07 13:25:27 +03:00
|
|
|
hasalpha = 1;
|
|
|
|
break;
|
2015-02-03 08:04:49 +03:00
|
|
|
#endif
|
2005-12-14 17:40:14 +03:00
|
|
|
default:
|
2015-02-07 13:25:27 +03:00
|
|
|
if (IS_WIN32 || ISALPHA(c)) {
|
2014-05-17 05:05:06 +04:00
|
|
|
hasalpha = 1;
|
2014-05-16 20:49:25 +04:00
|
|
|
}
|
2015-02-03 08:04:49 +03:00
|
|
|
break;
|
2004-04-09 12:06:01 +04:00
|
|
|
}
|
|
|
|
|
2008-07-08 03:00:58 +04:00
|
|
|
p = Next(p-1, pend, enc);
|
2004-04-09 12:06:01 +04:00
|
|
|
}
|
|
|
|
|
2018-09-22 04:11:40 +03:00
|
|
|
return hasmagical ? MAGICAL : hasalpha ? ALPHA : PLAIN;
|
2004-04-09 12:06:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Find separator in globbing pattern. */
|
|
|
|
static char *
|
2010-08-05 11:57:26 +04:00
|
|
|
find_dirsep(const char *p, const char *pend, int flags, rb_encoding *enc)
|
2004-04-09 12:06:01 +04:00
|
|
|
{
|
|
|
|
const int escape = !(flags & FNM_NOESCAPE);
|
|
|
|
|
|
|
|
register char c;
|
|
|
|
int open = 0;
|
|
|
|
|
2007-12-19 17:57:39 +03:00
|
|
|
while ((c = *p++) != 0) {
|
2004-04-09 12:06:01 +04:00
|
|
|
switch (c) {
|
|
|
|
case '[':
|
|
|
|
open = 1;
|
|
|
|
continue;
|
1999-08-13 09:45:20 +04:00
|
|
|
case ']':
|
2004-04-09 12:06:01 +04:00
|
|
|
open = 0;
|
|
|
|
continue;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2018-09-22 04:11:40 +03:00
|
|
|
case '{':
|
|
|
|
open = 1;
|
|
|
|
continue;
|
|
|
|
case '}':
|
|
|
|
open = 0;
|
|
|
|
continue;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2004-04-09 12:06:01 +04:00
|
|
|
case '/':
|
|
|
|
if (!open)
|
|
|
|
return (char *)p-1;
|
1999-08-13 09:45:20 +04:00
|
|
|
continue;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
case '\\':
|
2004-01-29 11:05:29 +03:00
|
|
|
if (escape && !(c = *p++))
|
2004-04-09 12:06:01 +04:00
|
|
|
return (char *)p-1;
|
2004-01-02 19:21:26 +03:00
|
|
|
continue;
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2008-07-08 03:00:58 +04:00
|
|
|
p = Next(p-1, pend, enc);
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
2004-01-02 19:21:26 +03:00
|
|
|
|
2004-04-09 12:06:01 +04:00
|
|
|
return (char *)p-1;
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
|
|
|
|
2007-12-31 09:43:32 +03:00
|
|
|
/* Remove escaping backslashes */
|
2012-12-01 10:05:33 +04:00
|
|
|
static char *
|
|
|
|
remove_backslashes(char *p, register const char *pend, rb_encoding *enc)
|
1999-08-13 09:45:20 +04:00
|
|
|
{
|
2004-01-02 19:21:26 +03:00
|
|
|
char *t = p;
|
|
|
|
char *s = p;
|
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
while (*p) {
|
2004-01-02 19:21:26 +03:00
|
|
|
if (*p == '\\') {
|
2004-01-29 11:05:29 +03:00
|
|
|
if (t != s)
|
2004-01-02 19:21:26 +03:00
|
|
|
memmove(t, s, p - s);
|
|
|
|
t += p - s;
|
|
|
|
s = ++p;
|
2004-01-29 11:05:29 +03:00
|
|
|
if (!*p) break;
|
2004-01-02 19:21:26 +03:00
|
|
|
}
|
2008-07-08 03:00:58 +04:00
|
|
|
Inc(p, pend, enc);
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
2004-01-02 19:21:26 +03:00
|
|
|
|
|
|
|
while (*p++);
|
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
if (t != s)
|
2004-01-02 19:21:26 +03:00
|
|
|
memmove(t, s, p - s); /* move '\0' too */
|
2012-12-01 10:05:33 +04:00
|
|
|
|
|
|
|
return p;
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
struct glob_pattern {
|
|
|
|
char *str;
|
|
|
|
enum glob_pattern_type type;
|
|
|
|
struct glob_pattern *next;
|
|
|
|
};
|
|
|
|
|
2006-10-30 17:23:46 +03:00
|
|
|
static void glob_free_pattern(struct glob_pattern *list);
|
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
static struct glob_pattern *
|
2010-08-05 11:57:26 +04:00
|
|
|
glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
|
2004-01-02 19:21:26 +03:00
|
|
|
{
|
2004-01-29 11:05:29 +03:00
|
|
|
struct glob_pattern *list, *tmp, **tail = &list;
|
2004-04-09 12:06:01 +04:00
|
|
|
int dirsep = 0; /* pattern is terminated with '/' */
|
2012-09-05 08:30:10 +04:00
|
|
|
int recursive = 0;
|
2004-01-29 11:05:29 +03:00
|
|
|
|
2010-08-05 11:57:26 +04:00
|
|
|
while (p < e && *p) {
|
2006-10-30 17:23:46 +03:00
|
|
|
tmp = GLOB_ALLOC(struct glob_pattern);
|
|
|
|
if (!tmp) goto error;
|
2014-05-16 12:22:41 +04:00
|
|
|
if (p + 2 < e && p[0] == '*' && p[1] == '*' && p[2] == '/') {
|
2004-04-09 12:06:01 +04:00
|
|
|
/* fold continuous RECURSIVEs (needed in glob_helper) */
|
2010-08-05 11:57:26 +04:00
|
|
|
do { p += 3; while (*p == '/') p++; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
|
2004-01-29 11:05:29 +03:00
|
|
|
tmp->type = RECURSIVE;
|
|
|
|
tmp->str = 0;
|
|
|
|
dirsep = 1;
|
2012-09-05 08:30:10 +04:00
|
|
|
recursive = 1;
|
2004-01-29 11:05:29 +03:00
|
|
|
}
|
|
|
|
else {
|
2010-08-05 11:57:26 +04:00
|
|
|
const char *m = find_dirsep(p, e, flags, enc);
|
2014-05-16 20:49:25 +04:00
|
|
|
const enum glob_pattern_type magic = has_magic(p, m, flags, enc);
|
2014-12-25 09:36:18 +03:00
|
|
|
const enum glob_pattern_type non_magic = (USE_NAME_ON_FS || FNM_SYSCASE) ? PLAIN : ALPHA;
|
2010-08-05 11:57:26 +04:00
|
|
|
char *buf;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2014-05-16 20:49:25 +04:00
|
|
|
if (!(FNM_SYSCASE || magic > non_magic) && !recursive && *m) {
|
2010-08-05 11:57:26 +04:00
|
|
|
const char *m2;
|
2014-05-16 20:49:25 +04:00
|
|
|
while (has_magic(m+1, m2 = find_dirsep(m+1, e, flags, enc), flags, enc) <= non_magic &&
|
2010-08-05 11:57:26 +04:00
|
|
|
*m2) {
|
|
|
|
m = m2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buf = GLOB_ALLOC_N(char, m-p+1);
|
2006-10-30 17:23:46 +03:00
|
|
|
if (!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
|
|
|
GLOB_FREE(tmp);
|
2006-10-30 17:23:46 +03:00
|
|
|
goto error;
|
|
|
|
}
|
2004-01-29 11:05:29 +03:00
|
|
|
memcpy(buf, p, m-p);
|
|
|
|
buf[m-p] = '\0';
|
2014-05-17 05:40:34 +04:00
|
|
|
tmp->type = magic > MAGICAL ? MAGICAL : magic > non_magic ? magic : PLAIN;
|
2004-01-29 11:05:29 +03:00
|
|
|
tmp->str = buf;
|
|
|
|
if (*m) {
|
|
|
|
dirsep = 1;
|
|
|
|
p = m + 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dirsep = 0;
|
|
|
|
p = m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*tail = tmp;
|
|
|
|
tail = &tmp->next;
|
|
|
|
}
|
2004-01-02 19:21:26 +03:00
|
|
|
|
2006-10-30 17:23:46 +03:00
|
|
|
tmp = GLOB_ALLOC(struct glob_pattern);
|
|
|
|
if (!tmp) {
|
2020-06-12 08:00:35 +03:00
|
|
|
goto error;
|
2006-10-30 17:23:46 +03:00
|
|
|
}
|
2004-01-29 11:05:29 +03:00
|
|
|
tmp->type = dirsep ? MATCH_DIR : MATCH_ALL;
|
|
|
|
tmp->str = 0;
|
|
|
|
*tail = tmp;
|
|
|
|
tmp->next = 0;
|
1999-08-13 09:45:20 +04:00
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
return list;
|
2020-06-12 08:00:35 +03:00
|
|
|
|
|
|
|
error:
|
|
|
|
*tail = 0;
|
|
|
|
glob_free_pattern(list);
|
|
|
|
return 0;
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
|
|
|
|
2004-01-29 11:05:29 +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
|
|
|
glob_free_pattern(struct glob_pattern *list)
|
2001-02-14 08:52:06 +03:00
|
|
|
{
|
2004-01-29 11:05:29 +03:00
|
|
|
while (list) {
|
|
|
|
struct glob_pattern *tmp = list;
|
|
|
|
list = list->next;
|
|
|
|
if (tmp->str)
|
* 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
|
|
|
GLOB_FREE(tmp->str);
|
|
|
|
GLOB_FREE(tmp);
|
2004-01-29 11:05:29 +03:00
|
|
|
}
|
2004-01-02 19:21:26 +03:00
|
|
|
}
|
2001-02-14 08:52:06 +03:00
|
|
|
|
2005-05-18 06:08:00 +04:00
|
|
|
static char *
|
2017-05-26 10:04:43 +03:00
|
|
|
join_path(const char *path, size_t len, int dirsep, const char *name, size_t namlen)
|
2004-01-02 19:21:26 +03:00
|
|
|
{
|
2012-12-01 10:05:33 +04:00
|
|
|
char *buf = GLOB_ALLOC_N(char, len+namlen+(dirsep?1:0)+1);
|
2004-11-10 10:17:53 +03:00
|
|
|
|
2006-10-30 17:23:46 +03:00
|
|
|
if (!buf) return 0;
|
2005-05-18 06:08:00 +04:00
|
|
|
memcpy(buf, path, len);
|
2004-01-29 11:05:29 +03:00
|
|
|
if (dirsep) {
|
2009-01-25 03:08:06 +03:00
|
|
|
buf[len++] = '/';
|
2004-01-29 11:05:29 +03:00
|
|
|
}
|
2012-12-01 10:05:33 +04:00
|
|
|
memcpy(buf+len, name, namlen);
|
|
|
|
buf[len+namlen] = '\0';
|
2004-01-29 11:05:29 +03:00
|
|
|
return buf;
|
2001-02-14 08:52:06 +03:00
|
|
|
}
|
|
|
|
|
2014-12-25 09:36:18 +03:00
|
|
|
#ifdef HAVE_GETATTRLIST
|
2017-01-02 01:20:38 +03:00
|
|
|
# if defined HAVE_FGETATTRLIST
|
|
|
|
# define is_case_sensitive(dirp, path) is_case_sensitive(dirp)
|
|
|
|
# else
|
|
|
|
# define is_case_sensitive(dirp, path) is_case_sensitive(path)
|
|
|
|
# endif
|
2015-01-08 06:53:45 +03:00
|
|
|
static int
|
2017-01-02 01:20:38 +03:00
|
|
|
is_case_sensitive(DIR *dirp, const char *path)
|
2015-01-08 06:53:45 +03:00
|
|
|
{
|
2015-02-24 06:34:10 +03:00
|
|
|
struct {
|
|
|
|
u_int32_t length;
|
|
|
|
vol_capabilities_attr_t cap[1];
|
|
|
|
} __attribute__((aligned(4), packed)) attrbuf[1];
|
2015-01-08 06:53:45 +03:00
|
|
|
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, 0, ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES};
|
2015-02-24 06:34:10 +03:00
|
|
|
const vol_capabilities_attr_t *const cap = attrbuf[0].cap;
|
2015-01-08 06:53:45 +03:00
|
|
|
const int idx = VOL_CAPABILITIES_FORMAT;
|
|
|
|
const uint32_t mask = VOL_CAP_FMT_CASE_SENSITIVE;
|
|
|
|
|
2017-01-02 01:20:38 +03:00
|
|
|
# if defined HAVE_FGETATTRLIST
|
2015-07-10 11:41:57 +03:00
|
|
|
if (fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
|
2015-01-08 06:53:45 +03:00
|
|
|
return -1;
|
2017-01-02 01:20:38 +03:00
|
|
|
# else
|
|
|
|
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
|
|
|
|
return -1;
|
|
|
|
# endif
|
2015-01-08 06:53:45 +03:00
|
|
|
if (!(cap->valid[idx] & mask))
|
|
|
|
return -1;
|
|
|
|
return (cap->capabilities[idx] & mask) != 0;
|
|
|
|
}
|
|
|
|
|
2014-12-25 09:36:18 +03:00
|
|
|
static char *
|
2015-07-02 15:32:09 +03:00
|
|
|
replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int flags, rb_pathtype_t *type)
|
2014-12-25 09:36:18 +03:00
|
|
|
{
|
2015-02-24 06:34:10 +03:00
|
|
|
struct {
|
|
|
|
u_int32_t length;
|
|
|
|
attrreference_t ref[1];
|
2015-07-02 10:15:09 +03:00
|
|
|
fsobj_type_t objtype;
|
2015-02-24 06:34:10 +03:00
|
|
|
char path[MAXPATHLEN * 3];
|
|
|
|
} __attribute__((aligned(4), packed)) attrbuf[1];
|
2015-07-02 10:15:09 +03:00
|
|
|
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_NAME|ATTR_CMN_OBJTYPE};
|
2015-02-24 06:34:10 +03:00
|
|
|
const attrreference_t *const ar = attrbuf[0].ref;
|
2014-12-25 09:36:18 +03:00
|
|
|
const char *name;
|
|
|
|
long len;
|
|
|
|
char *tmp;
|
2015-01-07 12:52:53 +03:00
|
|
|
IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil);
|
2014-12-25 09:36:18 +03:00
|
|
|
|
2015-07-02 10:15:09 +03:00
|
|
|
*type = path_noent;
|
2015-07-02 15:32:09 +03:00
|
|
|
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) {
|
|
|
|
if (!to_be_ignored(errno))
|
|
|
|
sys_warning(path, enc);
|
2014-12-25 09:36:18 +03:00
|
|
|
return path;
|
2015-07-02 15:32:09 +03:00
|
|
|
}
|
2014-12-25 09:36:18 +03:00
|
|
|
|
2015-07-02 10:15:09 +03:00
|
|
|
switch (attrbuf[0].objtype) {
|
|
|
|
case VREG: *type = path_regular; break;
|
|
|
|
case VDIR: *type = path_directory; break;
|
|
|
|
case VLNK: *type = path_symlink; break;
|
|
|
|
default: *type = path_exist; break;
|
|
|
|
}
|
2014-12-25 09:36:18 +03:00
|
|
|
name = (char *)ar + ar->attr_dataoffset;
|
|
|
|
len = (long)ar->attr_length - 1;
|
|
|
|
if (name + len > (char *)attrbuf + sizeof(attrbuf))
|
|
|
|
return path;
|
|
|
|
|
2015-01-07 12:52:53 +03:00
|
|
|
# if NORMALIZE_UTF8PATH
|
|
|
|
if (norm_p && has_nonascii(name, len)) {
|
2014-12-25 09:36:18 +03:00
|
|
|
if (!NIL_P(utf8str = rb_str_normalize_ospath(name, len))) {
|
|
|
|
RSTRING_GETMEM(utf8str, name, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
|
|
|
tmp = GLOB_REALLOC(path, base + len + 1);
|
|
|
|
if (tmp) {
|
|
|
|
path = tmp;
|
|
|
|
memcpy(path + base, name, len);
|
|
|
|
path[base + len] = '\0';
|
|
|
|
}
|
2015-01-07 12:52:53 +03:00
|
|
|
IF_NORMALIZE_UTF8PATH(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
|
2014-12-25 09:36:18 +03:00
|
|
|
return path;
|
|
|
|
}
|
2015-02-03 08:04:49 +03:00
|
|
|
#elif defined _WIN32
|
|
|
|
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
|
2015-08-20 02:31:19 +03:00
|
|
|
int rb_w32_reparse_symlink_p(const WCHAR *path);
|
2015-02-03 08:04:49 +03:00
|
|
|
|
|
|
|
static char *
|
2015-07-02 15:32:09 +03:00
|
|
|
replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int flags, rb_pathtype_t *type)
|
2015-02-03 08:04:49 +03:00
|
|
|
{
|
|
|
|
char *plainname = path;
|
|
|
|
volatile VALUE tmp = 0;
|
|
|
|
WIN32_FIND_DATAW fd;
|
2015-02-07 13:25:27 +03:00
|
|
|
WIN32_FILE_ATTRIBUTE_DATA fa;
|
2015-02-03 08:04:49 +03:00
|
|
|
WCHAR *wplain;
|
2015-02-07 13:25:27 +03:00
|
|
|
HANDLE h = INVALID_HANDLE_VALUE;
|
2015-02-03 08:04:49 +03:00
|
|
|
long wlen;
|
2015-07-03 01:13:17 +03:00
|
|
|
int e = 0;
|
2015-09-15 09:06:19 +03:00
|
|
|
if (!fundamental_encoding_p(enc)) {
|
2015-02-03 08:04:49 +03:00
|
|
|
tmp = rb_enc_str_new_cstr(plainname, enc);
|
|
|
|
tmp = rb_str_encode_ospath(tmp);
|
|
|
|
plainname = RSTRING_PTR(tmp);
|
|
|
|
}
|
|
|
|
wplain = rb_w32_mbstr_to_wstr(CP_UTF8, plainname, -1, &wlen);
|
|
|
|
if (tmp) rb_str_resize(tmp, 0);
|
|
|
|
if (!wplain) return path;
|
2015-07-03 01:13:17 +03:00
|
|
|
if (GetFileAttributesExW(wplain, GetFileExInfoStandard, &fa)) {
|
2015-02-07 13:25:27 +03:00
|
|
|
h = FindFirstFileW(wplain, &fd);
|
2015-07-03 01:13:17 +03:00
|
|
|
e = rb_w32_map_errno(GetLastError());
|
|
|
|
}
|
2015-08-20 02:31:19 +03:00
|
|
|
if (fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
|
|
|
if (!rb_w32_reparse_symlink_p(wplain))
|
|
|
|
fa.dwFileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;
|
|
|
|
}
|
2015-02-03 08:04:49 +03:00
|
|
|
free(wplain);
|
2015-07-02 10:15:09 +03:00
|
|
|
if (h == INVALID_HANDLE_VALUE) {
|
|
|
|
*type = path_noent;
|
2015-07-03 01:13:17 +03:00
|
|
|
if (e && !to_be_ignored(e)) {
|
|
|
|
errno = e;
|
2015-07-02 15:32:09 +03:00
|
|
|
sys_warning(path, enc);
|
2015-07-03 01:13:17 +03:00
|
|
|
}
|
2015-07-02 10:15:09 +03:00
|
|
|
return path;
|
|
|
|
}
|
2015-02-03 08:04:49 +03:00
|
|
|
FindClose(h);
|
2015-07-02 10:15:09 +03:00
|
|
|
*type =
|
|
|
|
(fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? path_symlink :
|
|
|
|
(fa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? path_directory :
|
|
|
|
path_regular;
|
2015-03-05 20:28:07 +03:00
|
|
|
if (tmp) {
|
2015-03-05 20:51:02 +03:00
|
|
|
char *buf;
|
2015-03-05 20:28:07 +03:00
|
|
|
tmp = rb_w32_conv_from_wchar(fd.cFileName, enc);
|
|
|
|
wlen = RSTRING_LEN(tmp);
|
2015-03-05 20:51:02 +03:00
|
|
|
buf = GLOB_REALLOC(path, base + wlen + 1);
|
|
|
|
if (buf) {
|
|
|
|
path = buf;
|
|
|
|
memcpy(path + base, RSTRING_PTR(tmp), wlen);
|
|
|
|
path[base + wlen] = 0;
|
|
|
|
}
|
2015-03-05 20:28:07 +03:00
|
|
|
rb_str_resize(tmp, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char *utf8filename;
|
|
|
|
wlen = WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1, NULL, 0, NULL, NULL);
|
|
|
|
utf8filename = GLOB_REALLOC(0, wlen);
|
2015-03-05 20:51:02 +03:00
|
|
|
if (utf8filename) {
|
|
|
|
char *buf;
|
|
|
|
WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1, utf8filename, wlen, NULL, NULL);
|
|
|
|
buf = GLOB_REALLOC(path, base + wlen + 1);
|
|
|
|
if (buf) {
|
|
|
|
path = buf;
|
|
|
|
memcpy(path + base, utf8filename, wlen);
|
|
|
|
path[base + wlen] = 0;
|
|
|
|
}
|
|
|
|
GLOB_FREE(utf8filename);
|
|
|
|
}
|
2015-03-05 20:28:07 +03:00
|
|
|
}
|
2015-02-03 08:04:49 +03:00
|
|
|
return path;
|
|
|
|
}
|
2016-06-20 14:00:17 +03:00
|
|
|
#elif USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
|
2015-02-03 08:04:49 +03:00
|
|
|
# error not implemented
|
2014-12-25 09:36:18 +03:00
|
|
|
#endif
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
#ifndef S_ISDIR
|
2010-12-08 14:38:29 +03:00
|
|
|
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
1999-08-13 09:45:20 +04:00
|
|
|
#endif
|
|
|
|
|
2004-01-02 19:21:26 +03:00
|
|
|
#ifndef S_ISLNK
|
|
|
|
# ifndef S_IFLNK
|
|
|
|
# define S_ISLNK(m) (0)
|
|
|
|
# else
|
2010-12-08 14:38:29 +03:00
|
|
|
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
2004-01-02 19:21:26 +03:00
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2002-09-12 10:27:15 +04:00
|
|
|
struct glob_args {
|
2008-07-09 06:11:21 +04:00
|
|
|
void (*func)(const char *, VALUE, void *);
|
2008-07-08 06:44:12 +04:00
|
|
|
const char *path;
|
2017-05-23 17:34:12 +03:00
|
|
|
const char *base;
|
2017-05-26 10:04:43 +03:00
|
|
|
size_t baselen;
|
2005-09-16 17:46:05 +04:00
|
|
|
VALUE value;
|
2008-07-08 06:44:12 +04:00
|
|
|
rb_encoding *enc;
|
2002-09-12 10:27:15 +04:00
|
|
|
};
|
|
|
|
|
2014-06-03 00:23:47 +04:00
|
|
|
#define glob_call_func(func, path, arg, enc) (*(func))((path), (arg), (void *)(enc))
|
|
|
|
|
2002-09-12 10:27:15 +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
|
|
|
glob_func_caller(VALUE val)
|
2002-09-12 10:27:15 +04:00
|
|
|
{
|
2002-09-13 18:46:44 +04:00
|
|
|
struct glob_args *args = (struct glob_args *)val;
|
2004-11-10 10:17:53 +03:00
|
|
|
|
2014-06-03 00:23:47 +04:00
|
|
|
glob_call_func(args->func, args->path, args->value, args->enc);
|
2002-09-12 10:27:15 +04:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2017-03-27 17:57:08 +03:00
|
|
|
struct glob_error_args {
|
|
|
|
const char *path;
|
|
|
|
rb_encoding *enc;
|
|
|
|
int error;
|
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
glob_func_warning(VALUE val)
|
|
|
|
{
|
|
|
|
struct glob_error_args *arg = (struct glob_error_args *)val;
|
|
|
|
rb_syserr_enc_warning(arg->error, arg->enc, "%s", arg->path);
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
static int
|
|
|
|
rb_glob_warning(const char *path, VALUE a, const void *enc, int error)
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
struct glob_error_args args;
|
|
|
|
|
|
|
|
args.path = path;
|
|
|
|
args.enc = enc;
|
|
|
|
args.error = error;
|
|
|
|
rb_protect(glob_func_warning, (VALUE)&args, &status);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-05-10 18:24:14 +03:00
|
|
|
NORETURN(static VALUE glob_func_error(VALUE val));
|
|
|
|
|
2017-03-27 17:57:08 +03:00
|
|
|
static VALUE
|
|
|
|
glob_func_error(VALUE val)
|
|
|
|
{
|
|
|
|
struct glob_error_args *arg = (struct glob_error_args *)val;
|
|
|
|
VALUE path = rb_enc_str_new_cstr(arg->path, arg->enc);
|
|
|
|
rb_syserr_fail_str(arg->error, path);
|
2020-05-10 18:24:14 +03:00
|
|
|
UNREACHABLE_RETURN(Qnil);
|
2017-03-27 17:57:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rb_glob_error(const char *path, VALUE a, const void *enc, int error)
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
struct glob_error_args args;
|
|
|
|
VALUE (*errfunc)(VALUE) = glob_func_error;
|
|
|
|
|
2021-11-27 12:27:37 +03:00
|
|
|
switch (error) {
|
|
|
|
case EACCES:
|
|
|
|
#ifdef ENOTCAPABLE
|
|
|
|
case ENOTCAPABLE:
|
|
|
|
#endif
|
2017-03-27 17:57:08 +03:00
|
|
|
errfunc = glob_func_warning;
|
|
|
|
}
|
|
|
|
args.path = path;
|
|
|
|
args.enc = enc;
|
|
|
|
args.error = error;
|
|
|
|
rb_protect(errfunc, (VALUE)&args, &status);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2020-01-17 18:21:11 +03:00
|
|
|
typedef struct rb_dirent {
|
|
|
|
long d_namlen;
|
|
|
|
const char *d_name;
|
|
|
|
#ifdef _WIN32
|
|
|
|
const char *d_altname;
|
|
|
|
#endif
|
|
|
|
uint8_t d_type;
|
|
|
|
} rb_dirent_t;
|
|
|
|
|
2015-03-08 10:57:38 +03:00
|
|
|
static inline int
|
2020-01-17 18:21:11 +03:00
|
|
|
dirent_match(const char *pat, rb_encoding *enc, const char *name, const rb_dirent_t *dp, int flags)
|
2015-03-08 10:57:38 +03:00
|
|
|
{
|
|
|
|
if (fnmatch(pat, enc, name, flags) == 0) return 1;
|
|
|
|
#ifdef _WIN32
|
2015-06-04 01:12:24 +03:00
|
|
|
if (dp->d_altname && (flags & FNM_SHORTNAME)) {
|
2015-03-08 10:57:38 +03:00
|
|
|
if (fnmatch(pat, enc, dp->d_altname, flags) == 0) return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-22 04:11:40 +03:00
|
|
|
struct push_glob_args {
|
|
|
|
int fd;
|
|
|
|
const char *path;
|
|
|
|
size_t baselen;
|
|
|
|
size_t namelen;
|
|
|
|
int dirsep; /* '/' should be placed before appending child entry's name to 'path'. */
|
|
|
|
rb_pathtype_t pathtype; /* type of 'path' */
|
|
|
|
int flags;
|
|
|
|
const ruby_glob_funcs_t *funcs;
|
|
|
|
VALUE arg;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct dirent_brace_args {
|
|
|
|
const char *name;
|
2020-01-17 18:21:11 +03:00
|
|
|
const rb_dirent_t *dp;
|
2018-09-22 04:11:40 +03:00
|
|
|
int flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
dirent_match_brace(const char *pattern, VALUE val, void *enc)
|
|
|
|
{
|
|
|
|
struct dirent_brace_args *arg = (struct dirent_brace_args *)val;
|
|
|
|
|
|
|
|
return dirent_match(pattern, enc, arg->name, arg->dp, arg->flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* join paths from pattern list of glob_make_pattern() */
|
2018-09-25 18:31:01 +03:00
|
|
|
static char*
|
2018-09-22 04:11:40 +03:00
|
|
|
join_path_from_pattern(struct glob_pattern **beg)
|
|
|
|
{
|
|
|
|
struct glob_pattern *p;
|
2018-09-25 18:31:01 +03:00
|
|
|
char *path = NULL;
|
2018-09-25 18:31:02 +03:00
|
|
|
size_t path_len = 0;
|
2018-09-22 04:11:40 +03:00
|
|
|
|
|
|
|
for (p = *beg; p; p = p->next) {
|
|
|
|
const char *str;
|
|
|
|
switch (p->type) {
|
|
|
|
case RECURSIVE:
|
|
|
|
str = "**";
|
|
|
|
break;
|
2019-01-16 17:06:37 +03:00
|
|
|
case MATCH_DIR:
|
|
|
|
/* append last slash */
|
|
|
|
str = "";
|
|
|
|
break;
|
2018-09-22 04:11:40 +03:00
|
|
|
default:
|
|
|
|
str = p->str;
|
2018-09-25 18:31:02 +03:00
|
|
|
if (!str) continue;
|
2018-09-22 04:11:40 +03:00
|
|
|
}
|
2018-09-25 18:31:01 +03:00
|
|
|
if (!path) {
|
|
|
|
path_len = strlen(str);
|
|
|
|
path = GLOB_ALLOC_N(char, path_len + 1);
|
2019-10-12 18:51:50 +03:00
|
|
|
if (path) {
|
|
|
|
memcpy(path, str, path_len);
|
|
|
|
path[path_len] = '\0';
|
|
|
|
}
|
2019-01-09 16:58:49 +03:00
|
|
|
}
|
|
|
|
else {
|
2018-09-25 18:31:01 +03:00
|
|
|
size_t len = strlen(str);
|
|
|
|
char *tmp;
|
|
|
|
tmp = GLOB_REALLOC(path, path_len + len + 2);
|
|
|
|
if (tmp) {
|
|
|
|
path = tmp;
|
|
|
|
path[path_len++] = '/';
|
|
|
|
memcpy(path + path_len, str, len);
|
|
|
|
path_len += len;
|
|
|
|
path[path_len] = '\0';
|
|
|
|
}
|
|
|
|
}
|
2018-09-22 04:11:40 +03:00
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int push_caller(const char *path, VALUE val, void *enc);
|
|
|
|
|
|
|
|
static int ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
|
|
|
|
rb_encoding *enc, VALUE var);
|
|
|
|
|
2020-01-17 18:21:11 +03:00
|
|
|
static const size_t rb_dirent_name_offset =
|
|
|
|
offsetof(rb_dirent_t, d_type) + sizeof(uint8_t);
|
|
|
|
|
|
|
|
static rb_dirent_t *
|
|
|
|
dirent_copy(const struct dirent *dp, rb_dirent_t *rdp)
|
|
|
|
{
|
|
|
|
if (!dp) return NULL;
|
|
|
|
size_t namlen = NAMLEN(dp);
|
|
|
|
const size_t altlen =
|
|
|
|
#ifdef _WIN32
|
|
|
|
dp->d_altlen ? dp->d_altlen + 1 :
|
|
|
|
#endif
|
|
|
|
0;
|
|
|
|
rb_dirent_t *newrdp = rdp;
|
|
|
|
if (!rdp && !(newrdp = malloc(rb_dirent_name_offset + namlen + 1 + altlen)))
|
|
|
|
return NULL;
|
|
|
|
newrdp->d_namlen = namlen;
|
|
|
|
if (!rdp) {
|
|
|
|
char *name = (char *)newrdp + rb_dirent_name_offset;
|
|
|
|
memcpy(name, dp->d_name, namlen);
|
|
|
|
name[namlen] = '\0';
|
|
|
|
#ifdef _WIN32
|
|
|
|
newrdp->d_altname = NULL;
|
|
|
|
if (altlen) {
|
|
|
|
char *const altname = name + namlen + 1;
|
|
|
|
memcpy(altname, dp->d_altname, altlen - 1);
|
|
|
|
altname[altlen - 1] = '\0';
|
|
|
|
newrdp->d_altname = altname;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
newrdp->d_name = name;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
newrdp->d_name = dp->d_name;
|
|
|
|
#ifdef _WIN32
|
|
|
|
newrdp->d_altname = dp->d_altname;
|
|
|
|
#endif
|
|
|
|
}
|
2022-03-17 14:05:15 +03:00
|
|
|
#if !EMULATE_IFTODT
|
2020-01-17 18:21:11 +03:00
|
|
|
newrdp->d_type = dp->d_type;
|
|
|
|
#else
|
|
|
|
newrdp->d_type = 0;
|
|
|
|
#endif
|
|
|
|
return newrdp;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
struct {
|
|
|
|
DIR *dirp;
|
|
|
|
rb_dirent_t ent;
|
|
|
|
} nosort;
|
|
|
|
struct {
|
|
|
|
size_t count, idx;
|
|
|
|
rb_dirent_t **entries;
|
|
|
|
} sort;
|
|
|
|
} ruby_glob_entries_t;
|
|
|
|
|
|
|
|
static int
|
|
|
|
glob_sort_cmp(const void *a, const void *b, void *e)
|
|
|
|
{
|
|
|
|
const rb_dirent_t *ent1 = *(void **)a;
|
|
|
|
const rb_dirent_t *ent2 = *(void **)b;
|
|
|
|
return strcmp(ent1->d_name, ent2->d_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
glob_dir_finish(ruby_glob_entries_t *ent, int flags)
|
|
|
|
{
|
|
|
|
if (flags & FNM_GLOB_NOSORT) {
|
|
|
|
closedir(ent->nosort.dirp);
|
|
|
|
ent->nosort.dirp = NULL;
|
|
|
|
}
|
|
|
|
else if (ent->sort.entries) {
|
|
|
|
for (size_t i = 0, count = ent->sort.count; i < count;) {
|
|
|
|
GLOB_FREE(ent->sort.entries[i++]);
|
|
|
|
}
|
|
|
|
GLOB_FREE(ent->sort.entries);
|
|
|
|
ent->sort.entries = NULL;
|
|
|
|
ent->sort.count = ent->sort.idx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ruby_glob_entries_t *
|
|
|
|
glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc)
|
|
|
|
{
|
|
|
|
MEMZERO(ent, ruby_glob_entries_t, 1);
|
|
|
|
if (flags & FNM_GLOB_NOSORT) {
|
|
|
|
ent->nosort.dirp = dirp;
|
2020-06-12 08:08:48 +03:00
|
|
|
return ent;
|
2020-01-17 18:21:11 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
void *newp;
|
|
|
|
struct dirent *dp;
|
|
|
|
size_t count = 0, capacity = 0;
|
|
|
|
ent->sort.count = 0;
|
|
|
|
ent->sort.idx = 0;
|
|
|
|
ent->sort.entries = 0;
|
|
|
|
#ifdef _WIN32
|
|
|
|
if ((capacity = dirp->nfiles) > 0) {
|
|
|
|
if (!(newp = GLOB_ALLOC_N(rb_dirent_t, capacity))) {
|
|
|
|
closedir(dirp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ent->sort.entries = newp;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
while ((dp = READDIR(dirp, enc)) != NULL) {
|
|
|
|
rb_dirent_t *rdp = dirent_copy(dp, NULL);
|
|
|
|
if (!rdp) {
|
2020-06-12 08:08:48 +03:00
|
|
|
goto nomem;
|
2020-01-17 18:21:11 +03:00
|
|
|
}
|
|
|
|
if (count >= capacity) {
|
|
|
|
capacity += 256;
|
|
|
|
if (!(newp = GLOB_REALLOC_N(ent->sort.entries, capacity)))
|
|
|
|
goto nomem;
|
|
|
|
ent->sort.entries = newp;
|
|
|
|
}
|
|
|
|
ent->sort.entries[count++] = rdp;
|
|
|
|
ent->sort.count = count;
|
|
|
|
}
|
|
|
|
closedir(dirp);
|
|
|
|
if (count < capacity) {
|
2020-01-20 03:30:17 +03:00
|
|
|
if (!(newp = GLOB_REALLOC_N(ent->sort.entries, count))) {
|
|
|
|
glob_dir_finish(ent, 0);
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-01-17 18:21:11 +03:00
|
|
|
ent->sort.entries = newp;
|
|
|
|
}
|
|
|
|
ruby_qsort(ent->sort.entries, ent->sort.count, sizeof(ent->sort.entries[0]),
|
|
|
|
glob_sort_cmp, NULL);
|
2020-06-12 08:08:48 +03:00
|
|
|
return ent;
|
2020-01-17 18:21:11 +03:00
|
|
|
}
|
2020-06-25 04:26:34 +03:00
|
|
|
|
|
|
|
nomem:
|
|
|
|
glob_dir_finish(ent, 0);
|
|
|
|
closedir(dirp);
|
|
|
|
return NULL;
|
2020-01-17 18:21:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static rb_dirent_t *
|
|
|
|
glob_getent(ruby_glob_entries_t *ent, int flags, rb_encoding *enc)
|
|
|
|
{
|
|
|
|
if (flags & FNM_GLOB_NOSORT) {
|
|
|
|
return dirent_copy(READDIR(ent->nosort.dirp, enc), &ent->nosort.ent);
|
|
|
|
}
|
|
|
|
else if (ent->sort.idx < ent->sort.count) {
|
|
|
|
return ent->sort.entries[ent->sort.idx++];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-12 10:27:15 +04:00
|
|
|
static 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
|
|
|
glob_helper(
|
2017-05-23 17:34:12 +03:00
|
|
|
int fd,
|
2008-07-08 06:44:12 +04:00
|
|
|
const char *path,
|
2017-05-26 10:04:43 +03:00
|
|
|
size_t baselen,
|
|
|
|
size_t namelen,
|
* 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
|
|
|
int dirsep, /* '/' should be placed before appending child entry's name to 'path'. */
|
2015-03-17 11:23:14 +03:00
|
|
|
rb_pathtype_t pathtype, /* type of 'path' */
|
* 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
|
|
|
struct glob_pattern **beg,
|
|
|
|
struct glob_pattern **end,
|
|
|
|
int flags,
|
2017-03-27 17:57:08 +03:00
|
|
|
const ruby_glob_funcs_t *funcs,
|
2008-07-08 06:44:12 +04:00
|
|
|
VALUE arg,
|
|
|
|
rb_encoding *enc)
|
1999-08-13 09:45:20 +04:00
|
|
|
{
|
|
|
|
struct stat st;
|
2002-09-12 10:27:15 +04:00
|
|
|
int status = 0;
|
2004-01-29 11:05:29 +03:00
|
|
|
struct glob_pattern **cur, **new_beg, **new_end;
|
2018-09-22 04:11:40 +03:00
|
|
|
int plain = 0, brace = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
|
2004-02-07 17:22:33 +03:00
|
|
|
int escape = !(flags & FNM_NOESCAPE);
|
2017-05-26 10:04:43 +03:00
|
|
|
size_t pathlen = baselen + namelen;
|
2004-01-29 11:05:29 +03:00
|
|
|
|
2020-12-10 16:00:11 +03:00
|
|
|
rb_check_stack_overflow();
|
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
for (cur = beg; cur < end; ++cur) {
|
|
|
|
struct glob_pattern *p = *cur;
|
|
|
|
if (p->type == RECURSIVE) {
|
|
|
|
recursive = 1;
|
|
|
|
p = p->next;
|
2004-01-02 19:21:26 +03:00
|
|
|
}
|
2004-01-29 11:05:29 +03:00
|
|
|
switch (p->type) {
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case PLAIN:
|
2004-02-07 17:22:33 +03:00
|
|
|
plain = 1;
|
2004-01-29 11:05:29 +03:00
|
|
|
break;
|
2014-05-16 20:49:25 +04:00
|
|
|
case ALPHA:
|
2016-06-20 14:00:17 +03:00
|
|
|
#if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
|
2014-12-25 09:36:18 +03:00
|
|
|
plain = 1;
|
|
|
|
#else
|
2004-02-07 17:22:33 +03:00
|
|
|
magical = 1;
|
2014-12-25 09:36:18 +03:00
|
|
|
#endif
|
2004-01-29 11:05:29 +03:00
|
|
|
break;
|
2018-09-22 04:11:40 +03:00
|
|
|
case BRACE:
|
2022-10-18 03:18:03 +03:00
|
|
|
if (!recursive || strchr(p->str, '/')) {
|
2018-09-25 18:31:02 +03:00
|
|
|
brace = 1;
|
|
|
|
}
|
2018-09-22 04:11:40 +03:00
|
|
|
break;
|
2014-05-17 05:05:06 +04:00
|
|
|
case MAGICAL:
|
|
|
|
magical = 2;
|
|
|
|
break;
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case MATCH_ALL:
|
2004-01-29 11:05:29 +03:00
|
|
|
match_all = 1;
|
|
|
|
break;
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case MATCH_DIR:
|
2004-01-29 11:05:29 +03:00
|
|
|
match_dir = 1;
|
|
|
|
break;
|
* compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
pack.c, parse.y, re.c, thread.c, vm.c, vm_dump.c, call_cfunc.ci,
thread_pthread.ci, thread_win32.ci: fixed indentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-05 08:25:10 +04:00
|
|
|
case RECURSIVE:
|
2005-06-28 17:08:32 +04:00
|
|
|
rb_bug("continuous RECURSIVEs");
|
2004-01-02 19:21:26 +03:00
|
|
|
}
|
|
|
|
}
|
1999-08-13 09:45:20 +04:00
|
|
|
|
2018-09-22 04:11:40 +03:00
|
|
|
if (brace) {
|
|
|
|
struct push_glob_args args;
|
2018-09-25 18:31:01 +03:00
|
|
|
char* brace_path = join_path_from_pattern(beg);
|
|
|
|
if (!brace_path) return -1;
|
2018-09-22 04:11:40 +03:00
|
|
|
args.fd = fd;
|
|
|
|
args.path = path;
|
|
|
|
args.baselen = baselen;
|
|
|
|
args.namelen = namelen;
|
|
|
|
args.dirsep = dirsep;
|
2018-09-26 05:23:21 +03:00
|
|
|
args.pathtype = pathtype;
|
2018-09-22 04:11:40 +03:00
|
|
|
args.flags = flags;
|
|
|
|
args.funcs = funcs;
|
|
|
|
args.arg = arg;
|
2018-09-25 18:31:01 +03:00
|
|
|
status = ruby_brace_expand(brace_path, flags, push_caller, (VALUE)&args, enc, Qfalse);
|
|
|
|
GLOB_FREE(brace_path);
|
|
|
|
return status;
|
2018-09-22 04:11:40 +03:00
|
|
|
}
|
|
|
|
|
2018-07-26 15:48:02 +03:00
|
|
|
if (*path) {
|
2015-03-17 11:23:14 +03:00
|
|
|
if (match_all && pathtype == path_unknown) {
|
2018-07-26 15:48:02 +03:00
|
|
|
if (do_lstat(fd, baselen, path, &st, flags, enc) == 0) {
|
2015-03-17 11:23:14 +03:00
|
|
|
pathtype = IFTODT(st.st_mode);
|
2004-02-08 04:07:09 +03:00
|
|
|
}
|
|
|
|
else {
|
2015-03-17 11:23:14 +03:00
|
|
|
pathtype = path_noent;
|
2004-02-08 04:07:09 +03:00
|
|
|
}
|
2004-01-29 11:05:29 +03:00
|
|
|
}
|
2017-08-03 07:13:12 +03:00
|
|
|
if (match_dir && (pathtype == path_unknown || pathtype == path_symlink)) {
|
2018-07-26 15:48:02 +03:00
|
|
|
if (do_stat(fd, baselen, path, &st, flags, enc) == 0) {
|
2015-03-17 11:23:14 +03:00
|
|
|
pathtype = IFTODT(st.st_mode);
|
2004-02-08 04:07:09 +03:00
|
|
|
}
|
|
|
|
else {
|
2015-03-17 11:23:14 +03:00
|
|
|
pathtype = path_noent;
|
2004-02-08 04:07:09 +03:00
|
|
|
}
|
2001-02-19 12:15:27 +03:00
|
|
|
}
|
2015-03-17 11:23:14 +03:00
|
|
|
if (match_all && pathtype > path_noent) {
|
2017-05-26 10:04:43 +03:00
|
|
|
const char *subpath = path + baselen + (baselen && path[baselen] == '/');
|
|
|
|
status = glob_call_func(funcs->match, subpath, arg, enc);
|
2004-02-08 04:07:09 +03:00
|
|
|
if (status) return status;
|
|
|
|
}
|
2015-03-17 11:23:14 +03:00
|
|
|
if (match_dir && pathtype == path_directory) {
|
2018-07-09 04:20:20 +03:00
|
|
|
int seplen = (baselen && path[baselen] == '/');
|
|
|
|
const char *subpath = path + baselen + seplen;
|
|
|
|
char *tmp = join_path(subpath, namelen - seplen, dirsep, "", 0);
|
2006-10-30 17:23:46 +03:00
|
|
|
if (!tmp) return -1;
|
2018-07-09 04:20:20 +03:00
|
|
|
status = glob_call_func(funcs->match, tmp, arg, enc);
|
* 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
|
|
|
GLOB_FREE(tmp);
|
2004-02-08 04:07:09 +03:00
|
|
|
if (status) return status;
|
|
|
|
}
|
2004-01-02 19:21:26 +03:00
|
|
|
}
|
2004-01-29 11:05:29 +03:00
|
|
|
|
2015-03-17 11:23:14 +03:00
|
|
|
if (pathtype == path_noent) return 0;
|
2004-01-29 11:05:29 +03:00
|
|
|
|
2014-05-16 20:49:25 +04:00
|
|
|
if (magical || recursive) {
|
2020-01-17 18:21:11 +03:00
|
|
|
rb_dirent_t *dp;
|
2017-11-15 10:24:26 +03:00
|
|
|
DIR *dirp;
|
2016-06-20 14:00:17 +03:00
|
|
|
# if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
|
2014-05-16 20:49:38 +04:00
|
|
|
char *plainname = 0;
|
|
|
|
# endif
|
2015-01-07 12:52:53 +03:00
|
|
|
IF_NORMALIZE_UTF8PATH(int norm_p);
|
2016-06-20 14:00:17 +03:00
|
|
|
# if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
|
2014-05-16 20:49:38 +04:00
|
|
|
if (cur + 1 == end && (*cur)->type <= ALPHA) {
|
|
|
|
plainname = join_path(path, pathlen, dirsep, (*cur)->str, strlen((*cur)->str));
|
|
|
|
if (!plainname) return -1;
|
2018-07-26 15:48:02 +03:00
|
|
|
dirp = do_opendir(fd, basename, plainname, flags, enc, funcs->error, arg, &status);
|
2014-05-16 20:49:38 +04:00
|
|
|
GLOB_FREE(plainname);
|
|
|
|
}
|
|
|
|
else
|
2017-03-27 17:57:08 +03:00
|
|
|
# else
|
|
|
|
;
|
2014-05-16 20:49:38 +04:00
|
|
|
# endif
|
2018-07-26 15:48:02 +03:00
|
|
|
dirp = do_opendir(fd, baselen, path, flags, enc, funcs->error, arg, &status);
|
2017-11-15 10:24:26 +03:00
|
|
|
if (dirp == NULL) {
|
2015-01-07 12:52:53 +03:00
|
|
|
# if FNM_SYSCASE || NORMALIZE_UTF8PATH
|
2014-05-17 05:05:06 +04:00
|
|
|
if ((magical < 2) && !recursive && (errno == EACCES)) {
|
2014-02-04 12:20:05 +04:00
|
|
|
/* no read permission, fallback */
|
|
|
|
goto literally;
|
|
|
|
}
|
|
|
|
# endif
|
2017-03-27 17:57:08 +03:00
|
|
|
return status;
|
2014-02-04 12:20:05 +04:00
|
|
|
}
|
2018-07-26 15:48:02 +03:00
|
|
|
IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp, *path ? path : "."));
|
2000-02-01 06:12:21 +03:00
|
|
|
|
2015-01-07 12:52:53 +03:00
|
|
|
# if NORMALIZE_UTF8PATH
|
|
|
|
if (!(norm_p || magical || recursive)) {
|
2017-11-15 10:24:26 +03:00
|
|
|
closedir(dirp);
|
2015-01-07 12:52:03 +03:00
|
|
|
goto literally;
|
|
|
|
}
|
2015-01-08 06:53:45 +03:00
|
|
|
# endif
|
|
|
|
# ifdef HAVE_GETATTRLIST
|
2017-11-15 10:24:26 +03:00
|
|
|
if (is_case_sensitive(dirp, path) == 0)
|
2015-01-08 06:53:45 +03:00
|
|
|
flags |= FNM_CASEFOLD;
|
2014-02-04 12:20:05 +04:00
|
|
|
# endif
|
2020-01-17 18:21:11 +03:00
|
|
|
ruby_glob_entries_t globent;
|
|
|
|
if (!glob_opendir(&globent, dirp, flags, enc)) {
|
|
|
|
status = 0;
|
|
|
|
if (funcs->error) {
|
|
|
|
status = (*funcs->error)(path, arg, enc, ENOMEM);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sys_warning(path, enc);
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
2021-01-12 12:17:02 +03:00
|
|
|
|
|
|
|
int skipdot = (flags & FNM_GLOB_SKIPDOT);
|
|
|
|
flags |= FNM_GLOB_SKIPDOT;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2020-01-17 18:21:11 +03:00
|
|
|
while ((dp = glob_getent(&globent, flags, enc)) != NULL) {
|
2012-09-05 05:44:36 +04:00
|
|
|
char *buf;
|
2015-03-17 11:23:14 +03:00
|
|
|
rb_pathtype_t new_pathtype = path_unknown;
|
2013-03-19 12:06:53 +04:00
|
|
|
const char *name;
|
|
|
|
size_t namlen;
|
2013-10-22 10:59:54 +04:00
|
|
|
int dotfile = 0;
|
2015-01-07 12:52:53 +03:00
|
|
|
IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil);
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2017-05-24 17:26:09 +03:00
|
|
|
name = dp->d_name;
|
2020-01-17 18:21:11 +03:00
|
|
|
namlen = dp->d_namlen;
|
2021-01-12 12:17:02 +03:00
|
|
|
if (name[0] == '.') {
|
2013-10-22 10:59:54 +04:00
|
|
|
++dotfile;
|
2017-05-24 17:26:09 +03:00
|
|
|
if (namlen == 1) {
|
2013-10-22 10:59:54 +04:00
|
|
|
/* unless DOTMATCH, skip current directories not to recurse infinitely */
|
2021-01-12 12:17:02 +03:00
|
|
|
if (recursive && !(flags & FNM_DOTMATCH)) continue;
|
|
|
|
if (skipdot) continue;
|
2013-10-22 10:59:54 +04:00
|
|
|
++dotfile;
|
2017-08-08 11:34:10 +03:00
|
|
|
new_pathtype = path_directory; /* force to skip stat/lstat */
|
2013-10-22 10:59:54 +04:00
|
|
|
}
|
2017-05-24 17:26:09 +03:00
|
|
|
else if (namlen == 2 && name[1] == '.') {
|
2013-10-22 10:59:54 +04:00
|
|
|
/* always skip parent directories not to recurse infinitely */
|
|
|
|
continue;
|
|
|
|
}
|
2012-09-05 05:44:36 +04:00
|
|
|
}
|
|
|
|
|
2015-01-07 12:52:53 +03:00
|
|
|
# if NORMALIZE_UTF8PATH
|
|
|
|
if (norm_p && has_nonascii(name, namlen)) {
|
2013-08-08 05:26:27 +04:00
|
|
|
if (!NIL_P(utf8str = rb_str_normalize_ospath(name, namlen))) {
|
2013-03-19 12:06:53 +04:00
|
|
|
RSTRING_GETMEM(utf8str, name, namlen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
buf = join_path(path, pathlen, dirsep, name, namlen);
|
2015-01-07 12:52:53 +03:00
|
|
|
IF_NORMALIZE_UTF8PATH(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
|
2006-10-30 17:23:46 +03:00
|
|
|
if (!buf) {
|
|
|
|
status = -1;
|
|
|
|
break;
|
|
|
|
}
|
2013-03-19 12:06:53 +04:00
|
|
|
name = buf + pathlen + (dirsep != 0);
|
2022-03-17 14:05:15 +03:00
|
|
|
#if !EMULATE_IFTODT
|
2017-08-08 11:34:10 +03:00
|
|
|
if (dp->d_type != DT_UNKNOWN) {
|
|
|
|
/* Got it. We need no more lstat. */
|
|
|
|
new_pathtype = dp->d_type;
|
|
|
|
}
|
2015-09-16 06:19:53 +03:00
|
|
|
#endif
|
2017-08-08 11:34:10 +03:00
|
|
|
if (recursive && dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1) &&
|
|
|
|
new_pathtype == path_unknown) {
|
2013-04-18 11:20:53 +04:00
|
|
|
/* RECURSIVE never match dot files unless FNM_DOTMATCH is set */
|
2018-07-26 15:48:02 +03:00
|
|
|
if (do_lstat(fd, baselen, buf, &st, flags, enc) == 0)
|
2015-03-17 11:23:14 +03:00
|
|
|
new_pathtype = IFTODT(st.st_mode);
|
2004-01-29 11:05:29 +03:00
|
|
|
else
|
2015-03-17 11:23:14 +03:00
|
|
|
new_pathtype = path_noent;
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2006-10-30 17:23:46 +03:00
|
|
|
new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, (end - beg) * 2);
|
|
|
|
if (!new_beg) {
|
2008-06-29 06:36:51 +04:00
|
|
|
GLOB_FREE(buf);
|
2006-10-30 17:23:46 +03:00
|
|
|
status = -1;
|
|
|
|
break;
|
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
for (cur = beg; cur < end; ++cur) {
|
|
|
|
struct glob_pattern *p = *cur;
|
2018-09-22 04:11:40 +03:00
|
|
|
struct dirent_brace_args args;
|
2004-01-29 11:05:29 +03:00
|
|
|
if (p->type == RECURSIVE) {
|
2015-03-17 11:23:14 +03:00
|
|
|
if (new_pathtype == path_directory || /* not symlink but real directory */
|
2017-08-08 11:34:10 +03:00
|
|
|
new_pathtype == path_exist) {
|
2017-08-08 13:43:19 +03:00
|
|
|
if (dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1))
|
|
|
|
*new_end++ = p; /* append recursive pattern */
|
2017-08-08 11:34:10 +03:00
|
|
|
}
|
2004-01-29 11:05:29 +03:00
|
|
|
p = p->next; /* 0 times recursion */
|
|
|
|
}
|
2014-05-16 20:49:25 +04:00
|
|
|
switch (p->type) {
|
2018-09-22 04:11:40 +03:00
|
|
|
case BRACE:
|
|
|
|
args.name = name;
|
|
|
|
args.dp = dp;
|
|
|
|
args.flags = flags;
|
|
|
|
if (ruby_brace_expand(p->str, flags, dirent_match_brace,
|
|
|
|
(VALUE)&args, enc, Qfalse) > 0)
|
|
|
|
*new_end++ = p->next;
|
|
|
|
break;
|
2014-05-16 20:49:25 +04:00
|
|
|
case ALPHA:
|
2016-06-20 14:00:17 +03:00
|
|
|
# if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
|
2014-05-16 20:49:38 +04:00
|
|
|
if (plainname) {
|
|
|
|
*new_end++ = p->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
# endif
|
2014-05-17 06:02:51 +04:00
|
|
|
case PLAIN:
|
2014-05-16 20:49:25 +04:00
|
|
|
case MAGICAL:
|
2015-03-08 10:57:38 +03:00
|
|
|
if (dirent_match(p->str, enc, name, dp, flags))
|
2004-01-29 11:05:29 +03:00
|
|
|
*new_end++ = p->next;
|
2014-05-16 20:49:25 +04:00
|
|
|
default:
|
|
|
|
break;
|
2004-01-29 11:05:29 +03:00
|
|
|
}
|
2004-01-02 19:21:26 +03:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2017-05-26 10:04:43 +03:00
|
|
|
status = glob_helper(fd, buf, baselen, name - buf - baselen + namlen, 1,
|
2015-09-30 11:12:14 +03:00
|
|
|
new_pathtype, new_beg, new_end,
|
2017-03-27 17:57:08 +03:00
|
|
|
flags, funcs, arg, enc);
|
* 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
|
|
|
GLOB_FREE(buf);
|
|
|
|
GLOB_FREE(new_beg);
|
2004-01-02 19:21:26 +03:00
|
|
|
if (status) break;
|
|
|
|
}
|
2004-01-29 11:05:29 +03:00
|
|
|
|
2020-01-17 18:21:11 +03:00
|
|
|
glob_dir_finish(&globent, flags);
|
2004-01-02 19:21:26 +03:00
|
|
|
}
|
2004-02-07 17:22:33 +03:00
|
|
|
else if (plain) {
|
2004-01-29 11:05:29 +03:00
|
|
|
struct glob_pattern **copy_beg, **copy_end, **cur2;
|
|
|
|
|
2015-01-07 12:52:53 +03:00
|
|
|
# if FNM_SYSCASE || NORMALIZE_UTF8PATH
|
2014-02-04 12:20:05 +04:00
|
|
|
literally:
|
|
|
|
# endif
|
2006-10-30 17:23:46 +03:00
|
|
|
copy_beg = copy_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
|
|
|
|
if (!copy_beg) return -1;
|
2004-01-29 11:05:29 +03:00
|
|
|
for (cur = beg; cur < end; ++cur)
|
2014-05-17 05:05:06 +04:00
|
|
|
*copy_end++ = (*cur)->type <= ALPHA ? *cur : 0;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2004-01-29 11:05:29 +03:00
|
|
|
for (cur = copy_beg; cur < copy_end; ++cur) {
|
|
|
|
if (*cur) {
|
2015-07-02 10:15:09 +03:00
|
|
|
rb_pathtype_t new_pathtype = path_unknown;
|
2005-05-18 06:08:00 +04:00
|
|
|
char *buf;
|
2004-11-10 10:17:53 +03:00
|
|
|
char *name;
|
2009-01-25 03:08:06 +03:00
|
|
|
size_t len = strlen((*cur)->str) + 1;
|
|
|
|
name = GLOB_ALLOC_N(char, len);
|
2006-10-30 17:23:46 +03:00
|
|
|
if (!name) {
|
|
|
|
status = -1;
|
|
|
|
break;
|
|
|
|
}
|
2009-01-25 03:08:06 +03:00
|
|
|
memcpy(name, (*cur)->str, len);
|
2012-12-01 10:05:33 +04:00
|
|
|
if (escape)
|
|
|
|
len = remove_backslashes(name, name+len-1, enc) - name;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2006-10-30 17:23:46 +03:00
|
|
|
new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
|
|
|
|
if (!new_beg) {
|
* 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
|
|
|
GLOB_FREE(name);
|
2006-10-30 17:23:46 +03:00
|
|
|
status = -1;
|
|
|
|
break;
|
|
|
|
}
|
2004-01-29 11:05:29 +03:00
|
|
|
*new_end++ = (*cur)->next;
|
|
|
|
for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
|
2008-07-08 06:44:12 +04:00
|
|
|
if (*cur2 && fnmatch((*cur2)->str, enc, name, flags) == 0) {
|
2004-01-29 11:05:29 +03:00
|
|
|
*new_end++ = (*cur2)->next;
|
|
|
|
*cur2 = 0;
|
|
|
|
}
|
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2013-03-19 12:04:26 +04:00
|
|
|
buf = join_path(path, pathlen, dirsep, name, len);
|
* 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
|
|
|
GLOB_FREE(name);
|
2006-10-30 17:23:46 +03:00
|
|
|
if (!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
|
|
|
GLOB_FREE(new_beg);
|
2006-10-30 17:23:46 +03:00
|
|
|
status = -1;
|
|
|
|
break;
|
|
|
|
}
|
2016-06-20 14:00:17 +03:00
|
|
|
#if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
|
2014-12-25 09:36:18 +03:00
|
|
|
if ((*cur)->type == ALPHA) {
|
2017-10-18 07:35:25 +03:00
|
|
|
buf = replace_real_basename(buf, pathlen + (dirsep != 0), enc,
|
|
|
|
IF_NORMALIZE_UTF8PATH(1)+0,
|
2015-07-02 15:32:09 +03:00
|
|
|
flags, &new_pathtype);
|
2017-03-27 17:57:08 +03:00
|
|
|
if (!buf) break;
|
2014-12-25 09:36:18 +03:00
|
|
|
}
|
|
|
|
#endif
|
2017-05-26 10:04:43 +03:00
|
|
|
status = glob_helper(fd, buf, baselen,
|
|
|
|
namelen + strlen(buf + pathlen), 1,
|
2015-09-30 11:12:14 +03:00
|
|
|
new_pathtype, new_beg, new_end,
|
2017-03-27 17:57:08 +03:00
|
|
|
flags, funcs, arg, enc);
|
* 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
|
|
|
GLOB_FREE(buf);
|
|
|
|
GLOB_FREE(new_beg);
|
2004-01-29 11:05:29 +03:00
|
|
|
if (status) break;
|
|
|
|
}
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
* 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
|
|
|
GLOB_FREE(copy_beg);
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
2004-01-02 19:21:26 +03:00
|
|
|
|
2002-09-12 10:27:15 +04:00
|
|
|
return status;
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2018-09-22 04:11:40 +03:00
|
|
|
static int
|
|
|
|
push_caller(const char *path, VALUE val, void *enc)
|
|
|
|
{
|
|
|
|
struct push_glob_args *arg = (struct push_glob_args *)val;
|
|
|
|
struct glob_pattern *list;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
list = glob_make_pattern(path, path + strlen(path), arg->flags, enc);
|
|
|
|
if (!list) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
status = glob_helper(arg->fd, arg->path, arg->baselen, arg->namelen, arg->dirsep,
|
|
|
|
arg->pathtype, &list, &list + 1, arg->flags, arg->funcs,
|
|
|
|
arg->arg, enc);
|
|
|
|
glob_free_pattern(list);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2019-03-21 16:32:03 +03:00
|
|
|
static int ruby_glob0(const char *path, int fd, const char *base, int flags,
|
|
|
|
const ruby_glob_funcs_t *funcs, VALUE arg, rb_encoding *enc);
|
|
|
|
|
|
|
|
struct push_glob0_args {
|
|
|
|
int fd;
|
|
|
|
const char *base;
|
|
|
|
int flags;
|
|
|
|
const ruby_glob_funcs_t *funcs;
|
|
|
|
VALUE arg;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
push_glob0_caller(const char *path, VALUE val, void *enc)
|
|
|
|
{
|
|
|
|
struct push_glob0_args *arg = (struct push_glob0_args *)val;
|
|
|
|
return ruby_glob0(path, arg->fd, arg->base, arg->flags, arg->funcs, arg->arg, enc);
|
|
|
|
}
|
|
|
|
|
2004-04-12 05:45:27 +04:00
|
|
|
static int
|
2017-05-23 17:34:12 +03:00
|
|
|
ruby_glob0(const char *path, int fd, const char *base, int flags,
|
2017-03-27 17:57:08 +03:00
|
|
|
const ruby_glob_funcs_t *funcs, VALUE arg,
|
|
|
|
rb_encoding *enc)
|
2002-03-13 13:11:09 +03:00
|
|
|
{
|
2004-01-29 11:05:29 +03:00
|
|
|
struct glob_pattern *list;
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
const char *root, *start;
|
2008-07-08 06:44:12 +04:00
|
|
|
char *buf;
|
2017-05-26 10:04:43 +03:00
|
|
|
size_t n, baselen = 0;
|
2017-05-23 16:47:36 +03:00
|
|
|
int status, dirsep = FALSE;
|
2004-01-02 19:21:26 +03:00
|
|
|
|
2008-07-08 06:44:12 +04:00
|
|
|
start = root = path;
|
2019-03-21 16:32:03 +03:00
|
|
|
|
|
|
|
if (*root == '{') {
|
|
|
|
struct push_glob0_args args;
|
|
|
|
args.fd = fd;
|
|
|
|
args.base = base;
|
|
|
|
args.flags = flags;
|
|
|
|
args.funcs = funcs;
|
|
|
|
args.arg = arg;
|
|
|
|
return ruby_brace_expand(path, flags, push_glob0_caller, (VALUE)&args, enc, Qfalse);
|
|
|
|
}
|
|
|
|
|
2005-12-14 17:40:14 +03:00
|
|
|
flags |= FNM_SYSCASE;
|
2004-01-02 19:21:26 +03:00
|
|
|
#if defined DOSISH
|
2012-01-25 06:32:06 +04:00
|
|
|
root = rb_enc_path_skip_prefix(root, root + strlen(root), enc);
|
2004-01-02 19:21:26 +03:00
|
|
|
#endif
|
|
|
|
|
2014-12-26 08:51:36 +03:00
|
|
|
if (*root == '/') root++;
|
2004-01-02 19:21:26 +03:00
|
|
|
|
2008-07-08 06:44:12 +04:00
|
|
|
n = root - start;
|
2017-05-23 16:47:36 +03:00
|
|
|
if (!n && base) {
|
|
|
|
n = strlen(base);
|
2017-05-26 10:04:43 +03:00
|
|
|
baselen = n;
|
2017-05-23 16:47:36 +03:00
|
|
|
start = base;
|
|
|
|
dirsep = TRUE;
|
|
|
|
}
|
2008-07-08 06:44:12 +04:00
|
|
|
buf = GLOB_ALLOC_N(char, n + 1);
|
|
|
|
if (!buf) return -1;
|
|
|
|
MEMCPY(buf, start, char, n);
|
|
|
|
buf[n] = '\0';
|
2004-01-29 11:05:29 +03:00
|
|
|
|
2010-08-05 11:57:26 +04:00
|
|
|
list = glob_make_pattern(root, root + strlen(root), flags, enc);
|
2006-10-30 17:23:46 +03:00
|
|
|
if (!list) {
|
2008-07-08 06:44:12 +04:00
|
|
|
GLOB_FREE(buf);
|
2006-10-30 17:23:46 +03:00
|
|
|
return -1;
|
|
|
|
}
|
2017-05-26 10:04:43 +03:00
|
|
|
status = glob_helper(fd, buf, baselen, n-baselen, dirsep,
|
|
|
|
path_unknown, &list, &list + 1,
|
2017-03-27 17:57:08 +03:00
|
|
|
flags, funcs, arg, enc);
|
2004-01-29 11:05:29 +03:00
|
|
|
glob_free_pattern(list);
|
2008-07-08 06:44:12 +04:00
|
|
|
GLOB_FREE(buf);
|
2004-01-29 11:05:29 +03:00
|
|
|
|
2004-04-12 05:45:27 +04:00
|
|
|
return status;
|
2002-03-13 13:11:09 +03:00
|
|
|
}
|
|
|
|
|
2005-09-14 17:41:02 +04:00
|
|
|
int
|
2005-09-16 17:46:05 +04:00
|
|
|
ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
|
2005-09-14 17:41:02 +04:00
|
|
|
{
|
2017-03-27 17:57:08 +03:00
|
|
|
ruby_glob_funcs_t funcs;
|
|
|
|
funcs.match = func;
|
2020-02-07 08:14:05 +03:00
|
|
|
funcs.error = 0;
|
2017-05-23 17:34:12 +03:00
|
|
|
return ruby_glob0(path, AT_FDCWD, 0, flags & ~GLOB_VERBOSE,
|
2017-03-27 17:57:08 +03:00
|
|
|
&funcs, arg, rb_ascii8bit_encoding());
|
2005-09-14 17:41:02 +04:00
|
|
|
}
|
2004-11-10 10:17:53 +03:00
|
|
|
|
2005-09-14 17:41:02 +04:00
|
|
|
static int
|
2008-07-09 06:11:21 +04:00
|
|
|
rb_glob_caller(const char *path, VALUE a, void *enc)
|
2004-11-10 10:17:53 +03:00
|
|
|
{
|
2005-09-14 17:41:02 +04:00
|
|
|
int status;
|
|
|
|
struct glob_args *args = (struct glob_args *)a;
|
|
|
|
|
2005-09-16 17:46:05 +04:00
|
|
|
args->path = path;
|
2005-09-14 17:41:02 +04:00
|
|
|
rb_protect(glob_func_caller, a, &status);
|
|
|
|
return status;
|
2004-11-10 10:17:53 +03:00
|
|
|
}
|
|
|
|
|
2017-03-27 17:57:08 +03:00
|
|
|
static const ruby_glob_funcs_t rb_glob_funcs = {
|
|
|
|
rb_glob_caller, rb_glob_error,
|
|
|
|
};
|
|
|
|
|
2016-11-05 18:49:29 +03:00
|
|
|
void
|
|
|
|
rb_glob(const char *path, void (*func)(const char *, VALUE, void *), VALUE arg)
|
2000-11-20 04:24:28 +03:00
|
|
|
{
|
2005-09-14 17:41:02 +04:00
|
|
|
struct glob_args args;
|
2016-11-05 18:49:29 +03:00
|
|
|
int status;
|
2004-11-10 10:17:53 +03:00
|
|
|
|
|
|
|
args.func = func;
|
2005-09-16 17:46:05 +04:00
|
|
|
args.value = arg;
|
2016-11-05 18:49:29 +03:00
|
|
|
args.enc = rb_ascii8bit_encoding();
|
2005-09-14 17:41:02 +04:00
|
|
|
|
2017-05-23 17:34:12 +03:00
|
|
|
status = ruby_glob0(path, AT_FDCWD, 0, GLOB_VERBOSE, &rb_glob_funcs,
|
2017-03-27 17:57:08 +03:00
|
|
|
(VALUE)&args, args.enc);
|
2006-10-30 17:23:46 +03:00
|
|
|
if (status) GLOB_JUMP_TAG(status);
|
2000-11-20 04:24:28 +03:00
|
|
|
}
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
static void
|
2008-07-09 06:11:21 +04:00
|
|
|
push_pattern(const char *path, VALUE ary, void *enc)
|
1999-08-13 09:45:20 +04:00
|
|
|
{
|
2016-02-20 07:04:59 +03:00
|
|
|
#if defined _WIN32 || defined __APPLE__
|
2015-02-25 09:59:39 +03:00
|
|
|
VALUE name = rb_utf8_str_new_cstr(path);
|
|
|
|
rb_encoding *eenc = rb_default_internal_encoding();
|
|
|
|
name = rb_str_conv_enc(name, NULL, eenc ? eenc : enc);
|
|
|
|
#else
|
|
|
|
VALUE name = rb_external_str_new_with_enc(path, strlen(path), enc);
|
|
|
|
#endif
|
|
|
|
rb_ary_push(ary, name);
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-07-07 21:29:44 +04:00
|
|
|
static int
|
2008-07-08 06:44:12 +04:00
|
|
|
ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
|
2017-07-25 08:55:22 +03:00
|
|
|
rb_encoding *enc, VALUE var)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2004-04-15 14:32:09 +04:00
|
|
|
const int escape = !(flags & FNM_NOESCAPE);
|
2005-05-18 06:08:00 +04:00
|
|
|
const char *p = str;
|
2008-07-08 03:00:58 +04:00
|
|
|
const char *pend = p + strlen(p);
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
const char *s = p;
|
2017-10-27 11:40:40 +03:00
|
|
|
const char *lbrace = 0, *rbrace = 0;
|
2004-04-15 14:32:09 +04:00
|
|
|
int nest = 0, status = 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
while (*p) {
|
2004-04-15 14:32:09 +04:00
|
|
|
if (*p == '{' && nest++ == 0) {
|
1998-01-16 15:13:05 +03:00
|
|
|
lbrace = p;
|
|
|
|
}
|
2015-10-22 07:16:21 +03:00
|
|
|
if (*p == '}' && lbrace && --nest == 0) {
|
1998-01-16 15:13:05 +03:00
|
|
|
rbrace = p;
|
|
|
|
break;
|
|
|
|
}
|
2004-04-15 14:32:09 +04:00
|
|
|
if (*p == '\\' && escape) {
|
|
|
|
if (!*++p) break;
|
|
|
|
}
|
2008-07-08 03:00:58 +04:00
|
|
|
Inc(p, pend, enc);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-05-19 19:54:37 +04:00
|
|
|
if (lbrace && rbrace) {
|
* dir.c, dln.c, parse.y, re.c, ruby.c, sprintf.c, strftime.c,
string.c, util.c, variable.c: use strlcpy, memcpy and snprintf
instead of strcpy, strncpy and sprintf.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22984 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-17 04:29:17 +03:00
|
|
|
size_t len = strlen(s) + 1;
|
2017-10-27 11:40:40 +03:00
|
|
|
char *buf = GLOB_ALLOC_N(char, len);
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
long shift;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2006-10-30 17:23:46 +03:00
|
|
|
if (!buf) return -1;
|
1998-01-16 15:13:05 +03:00
|
|
|
memcpy(buf, s, lbrace-s);
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
shift = (lbrace-s);
|
1998-01-16 15:13:05 +03:00
|
|
|
p = lbrace;
|
2004-04-15 14:32:09 +04:00
|
|
|
while (p < rbrace) {
|
|
|
|
const char *t = ++p;
|
|
|
|
nest = 0;
|
|
|
|
while (p < rbrace && !(*p == ',' && nest == 0)) {
|
|
|
|
if (*p == '{') nest++;
|
|
|
|
if (*p == '}') nest--;
|
|
|
|
if (*p == '\\' && escape) {
|
|
|
|
if (++p == rbrace) break;
|
|
|
|
}
|
2008-07-08 03:00:58 +04:00
|
|
|
Inc(p, pend, enc);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
memcpy(buf+shift, t, p-t);
|
* dir.c, dln.c, parse.y, re.c, ruby.c, sprintf.c, strftime.c,
string.c, util.c, variable.c: use strlcpy, memcpy and snprintf
instead of strcpy, strncpy and sprintf.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22984 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-17 04:29:17 +03:00
|
|
|
strlcpy(buf+shift+(p-t), rbrace+1, len-(shift+(p-t)));
|
2017-07-25 08:55:22 +03:00
|
|
|
status = ruby_brace_expand(buf, flags, func, arg, enc, var);
|
2004-04-12 05:45:27 +04:00
|
|
|
if (status) break;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
* 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
|
|
|
GLOB_FREE(buf);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2004-04-15 14:32:09 +04:00
|
|
|
else if (!lbrace && !rbrace) {
|
2014-06-03 00:23:47 +04:00
|
|
|
status = glob_call_func(func, s, arg, enc);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2004-04-12 05:45:27 +04:00
|
|
|
|
2017-07-25 08:55:22 +03:00
|
|
|
RB_GC_GUARD(var);
|
2004-04-12 05:45:27 +04:00
|
|
|
return status;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2005-09-16 17:46:05 +04:00
|
|
|
struct brace_args {
|
2017-03-27 17:57:08 +03:00
|
|
|
ruby_glob_funcs_t funcs;
|
2005-09-16 17:46:05 +04:00
|
|
|
VALUE value;
|
|
|
|
int flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2008-07-09 06:11:21 +04:00
|
|
|
glob_brace(const char *path, VALUE val, void *enc)
|
2005-09-16 17:46:05 +04:00
|
|
|
{
|
|
|
|
struct brace_args *arg = (struct brace_args *)val;
|
|
|
|
|
2017-05-23 17:34:12 +03:00
|
|
|
return ruby_glob0(path, AT_FDCWD, 0, arg->flags, &arg->funcs, arg->value, enc);
|
2005-09-16 17:46:05 +04:00
|
|
|
}
|
|
|
|
|
2015-04-01 05:42:19 +03:00
|
|
|
int
|
|
|
|
ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
|
2005-09-16 17:46:05 +04:00
|
|
|
{
|
|
|
|
struct brace_args args;
|
|
|
|
|
2015-04-01 05:42:19 +03:00
|
|
|
flags &= ~GLOB_VERBOSE;
|
2017-03-27 17:57:08 +03:00
|
|
|
args.funcs.match = func;
|
2020-02-07 08:14:05 +03:00
|
|
|
args.funcs.error = 0;
|
2005-09-16 17:46:05 +04:00
|
|
|
args.value = arg;
|
|
|
|
args.flags = flags;
|
2017-07-25 08:55:22 +03:00
|
|
|
return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args, enc, Qfalse);
|
2005-09-16 17:46:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
|
|
|
|
{
|
2015-04-01 05:42:19 +03:00
|
|
|
return ruby_brace_glob_with_enc(str, flags, func, arg, rb_ascii8bit_encoding());
|
* 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
|
|
|
}
|
|
|
|
|
2005-09-16 17:46:05 +04:00
|
|
|
static int
|
2017-05-23 16:47:36 +03:00
|
|
|
push_glob(VALUE ary, VALUE str, VALUE base, int flags)
|
2005-09-16 17:46:05 +04:00
|
|
|
{
|
2018-09-22 04:11:40 +03:00
|
|
|
struct glob_args args;
|
|
|
|
int fd;
|
2008-07-09 06:11:21 +04:00
|
|
|
rb_encoding *enc = rb_enc_get(str);
|
2005-09-16 17:46:05 +04:00
|
|
|
|
2016-02-20 07:04:59 +03:00
|
|
|
#if defined _WIN32 || defined __APPLE__
|
2015-02-25 09:59:39 +03:00
|
|
|
str = rb_str_encode_ospath(str);
|
|
|
|
#endif
|
2015-10-29 08:30:50 +03:00
|
|
|
if (rb_enc_to_index(enc) == ENCINDEX_US_ASCII)
|
2015-09-15 09:06:19 +03:00
|
|
|
enc = rb_filesystem_encoding();
|
2015-10-29 08:30:50 +03:00
|
|
|
if (rb_enc_to_index(enc) == ENCINDEX_US_ASCII)
|
2015-09-15 09:06:19 +03:00
|
|
|
enc = rb_ascii8bit_encoding();
|
2015-04-01 05:09:18 +03:00
|
|
|
flags |= GLOB_VERBOSE;
|
2018-09-22 04:11:40 +03:00
|
|
|
args.func = push_pattern;
|
|
|
|
args.value = ary;
|
|
|
|
args.enc = enc;
|
|
|
|
args.base = 0;
|
|
|
|
fd = AT_FDCWD;
|
2017-05-23 17:34:12 +03:00
|
|
|
if (!NIL_P(base)) {
|
|
|
|
if (!RB_TYPE_P(base, T_STRING) || !rb_enc_check(str, base)) {
|
2023-11-21 21:31:05 +03:00
|
|
|
struct dir_data *dirp = RTYPEDDATA_GET_DATA(base);
|
2017-05-23 17:34:12 +03:00
|
|
|
if (!dirp->dir) dir_closed();
|
|
|
|
#ifdef HAVE_DIRFD
|
2018-09-22 04:11:40 +03:00
|
|
|
if ((fd = dirfd(dirp->dir)) == -1)
|
2017-05-23 17:34:12 +03:00
|
|
|
rb_sys_fail_path(dir_inspect(base));
|
|
|
|
#endif
|
|
|
|
base = dirp->path;
|
|
|
|
}
|
2018-09-22 04:11:40 +03:00
|
|
|
args.base = RSTRING_PTR(base);
|
2017-05-23 16:47:36 +03:00
|
|
|
}
|
2016-02-20 07:04:59 +03:00
|
|
|
#if defined _WIN32 || defined __APPLE__
|
2015-02-25 09:59:39 +03:00
|
|
|
enc = rb_utf8_encoding();
|
|
|
|
#endif
|
2008-07-09 06:11:21 +04:00
|
|
|
|
2018-09-22 04:11:40 +03:00
|
|
|
return ruby_glob0(RSTRING_PTR(str), fd, args.base, flags, &rb_glob_funcs,
|
|
|
|
(VALUE)&args, enc);
|
2005-09-16 17:46:05 +04:00
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2017-05-23 16:47:36 +03:00
|
|
|
rb_push_glob(VALUE str, VALUE base, int flags) /* '\0' is delimiter */
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2002-03-13 13:11:09 +03:00
|
|
|
VALUE ary;
|
2019-09-02 09:08:53 +03:00
|
|
|
int status;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2018-03-28 12:58:52 +03:00
|
|
|
/* can contain null bytes as separators */
|
2019-09-02 09:08:53 +03:00
|
|
|
if (!RB_TYPE_P(str, T_STRING)) {
|
2018-03-28 12:58:52 +03:00
|
|
|
FilePathValue(str);
|
|
|
|
}
|
2019-09-02 09:08:53 +03:00
|
|
|
else if (!rb_str_to_cstr(str)) {
|
|
|
|
rb_raise(rb_eArgError, "nul-separated glob pattern is deprecated");
|
|
|
|
}
|
2018-03-28 12:58:52 +03:00
|
|
|
else {
|
|
|
|
rb_enc_check(str, rb_enc_from_encoding(rb_usascii_encoding()));
|
|
|
|
}
|
2004-10-19 14:25:23 +04:00
|
|
|
ary = rb_ary_new();
|
2004-11-10 10:17:53 +03:00
|
|
|
|
2019-09-02 09:08:53 +03:00
|
|
|
status = push_glob(ary, str, base, flags);
|
|
|
|
if (status) GLOB_JUMP_TAG(status);
|
2004-04-12 05:45:27 +04:00
|
|
|
|
2005-09-16 17:46:05 +04:00
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2020-03-24 18:53:11 +03:00
|
|
|
dir_globs(VALUE args, VALUE base, int flags)
|
2005-09-16 17:46:05 +04:00
|
|
|
{
|
|
|
|
VALUE ary = rb_ary_new();
|
|
|
|
long i;
|
|
|
|
|
2020-03-24 18:53:11 +03:00
|
|
|
for (i = 0; i < RARRAY_LEN(args); ++i) {
|
2005-09-16 17:46:05 +04:00
|
|
|
int status;
|
2020-03-24 18:53:11 +03:00
|
|
|
VALUE str = RARRAY_AREF(args, i);
|
2018-03-28 12:58:52 +03:00
|
|
|
FilePathValue(str);
|
2017-05-23 16:47:36 +03:00
|
|
|
status = push_glob(ary, str, base, flags);
|
2006-10-30 17:23:46 +03:00
|
|
|
if (status) GLOB_JUMP_TAG(status);
|
2004-10-19 14:25:23 +04:00
|
|
|
}
|
2020-03-24 18:53:11 +03:00
|
|
|
RB_GC_GUARD(args);
|
2005-09-16 17:46:05 +04:00
|
|
|
|
2002-03-13 13:11:09 +03:00
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
2020-03-24 17:18:36 +03:00
|
|
|
static VALUE
|
|
|
|
dir_glob_option_base(VALUE base)
|
|
|
|
{
|
2022-11-22 15:49:54 +03:00
|
|
|
if (NIL_OR_UNDEF_P(base)) {
|
2020-03-24 17:18:36 +03:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
#if USE_OPENDIR_AT
|
|
|
|
if (rb_typeddata_is_kind_of(base, &dir_data_type)) {
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
FilePathValue(base);
|
|
|
|
if (!RSTRING_LEN(base)) return Qnil;
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dir_glob_option_sort(VALUE sort)
|
|
|
|
{
|
2022-05-24 10:48:34 +03:00
|
|
|
return (rb_bool_expected(sort, "sort", TRUE) ? 0 : FNM_GLOB_NOSORT);
|
2020-03-24 17:18:36 +03:00
|
|
|
}
|
|
|
|
|
2002-03-13 13:11:09 +03:00
|
|
|
static VALUE
|
2020-03-24 18:53:11 +03:00
|
|
|
dir_s_aref(rb_execution_context_t *ec, VALUE obj, VALUE args, VALUE base, VALUE sort)
|
2002-03-13 13:11:09 +03:00
|
|
|
{
|
2020-03-24 18:53:11 +03:00
|
|
|
const int flags = dir_glob_option_sort(sort);
|
|
|
|
base = dir_glob_option_base(base);
|
|
|
|
if (RARRAY_LEN(args) == 1) {
|
|
|
|
return rb_push_glob(RARRAY_AREF(args, 0), base, flags);
|
2005-09-16 17:46:05 +04:00
|
|
|
}
|
2020-03-24 18:53:11 +03:00
|
|
|
return dir_globs(args, base, flags);
|
2002-03-13 13:11:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2020-03-24 17:18:36 +03:00
|
|
|
dir_s_glob(rb_execution_context_t *ec, VALUE obj, VALUE str, VALUE rflags, VALUE base, VALUE sort)
|
2002-03-13 13:11:09 +03:00
|
|
|
{
|
2020-03-24 17:18:36 +03:00
|
|
|
VALUE ary = rb_check_array_type(str);
|
2021-06-17 20:13:33 +03:00
|
|
|
const int flags = (NUM2INT(rflags) | dir_glob_option_sort(sort)) & ~FNM_CASEFOLD;
|
2020-03-24 17:18:36 +03:00
|
|
|
base = dir_glob_option_base(base);
|
2005-09-16 17:46:05 +04:00
|
|
|
if (NIL_P(ary)) {
|
2017-05-23 16:47:36 +03:00
|
|
|
ary = rb_push_glob(str, base, flags);
|
2005-09-16 17:46:05 +04:00
|
|
|
}
|
|
|
|
else {
|
2020-03-24 18:53:11 +03:00
|
|
|
ary = dir_globs(ary, base, flags);
|
2005-09-16 17:46:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (rb_block_given_p()) {
|
|
|
|
rb_ary_each(ary);
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
return ary;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
static VALUE
|
2008-06-17 02:29:05 +04:00
|
|
|
dir_open_dir(int argc, VALUE *argv)
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
{
|
Make rb_scan_args handle keywords more similar to Ruby methods (#2460)
Cfuncs that use rb_scan_args with the : entry suffer similar keyword
argument separation issues that Ruby methods suffer if the cfuncs
accept optional or variable arguments.
This makes the following changes to : handling.
* Treats as **kw, prompting keyword argument separation warnings
if called with a positional hash.
* Do not look for an option hash if empty keywords are provided.
For backwards compatibility, treat an empty keyword splat as a empty
mandatory positional hash argument, but emit a a warning, as this
behavior will be removed in Ruby 3. The argument number check
needs to be moved lower so it can correctly handle an empty
positional argument being added.
* If the last argument is nil and it is necessary to treat it as an option
hash in order to make sure all arguments are processed, continue to
treat the last argument as the option hash. Emit a warning in this case,
as this behavior will be removed in Ruby 3.
* If splitting the keyword hash into two hashes, issue a warning, as we
will not be splitting hashes in Ruby 3.
* If the keyword argument is required to fill a mandatory positional
argument, continue to do so, but emit a warning as this behavior will
be going away in Ruby 3.
* If keyword arguments are provided and the last argument is not a hash,
that indicates something wrong. This can happen if a cfunc is calling
rb_scan_args multiple times, and providing arguments that were not
passed to it from Ruby. Callers need to switch to the new
rb_scan_args_kw function, which allows passing of whether keywords
were provided.
This commit fixes all warnings caused by the changes above.
It switches some function calls to *_kw versions with appropriate
kw_splat flags. If delegating arguments, RB_PASS_CALLED_KEYWORDS
is used. If creating new arguments, RB_PASS_KEYWORDS is used if
the last argument is a hash to be treated as keywords.
In open_key_args in io.c, use rb_scan_args_kw.
In this case, the arguments provided come from another C
function, not Ruby. The last argument may or may not be a hash,
so we can't set keyword argument mode. However, if it is a
hash, we don't want to warn when treating it as keywords.
In Ruby files, make sure to appropriately use keyword splats
or literal keywords when calling Cfuncs that now issue keyword
argument separation warnings through rb_scan_args. Also, make
sure not to pass nil in place of an option hash.
Work around Kernel#warn warnings due to problems in the Rubygems
override of the method. There is an open pull request to fix
these issues in Rubygems, but part of the Rubygems tests for
their override fail on ruby-head due to rb_scan_args not
recognizing empty keyword splats, which this commit fixes.
Implementation wise, adding rb_scan_args_kw is kind of a pain,
because rb_scan_args takes a variable number of arguments.
In order to not duplicate all the code, the function internals need
to be split into two functions taking a va_list, and to avoid passing
in a ton of arguments, a single struct argument is used to handle
the variables previously local to the function.
2019-09-25 21:18:49 +03:00
|
|
|
VALUE dir = rb_funcallv_kw(rb_cDir, rb_intern("open"), argc, argv, RB_PASS_CALLED_KEYWORDS);
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
|
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
|
|
|
rb_check_typeddata(dir, &dir_data_type);
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.foreach(dirpath, encoding: 'UTF-8') {|entry_name| ... } -> nil
|
|
|
|
*
|
|
|
|
* Calls the block with each entry name in the directory at +dirpath+;
|
|
|
|
* sets the given encoding onto each passed +entry_name+:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.foreach('/example') {|entry_name| p entry_name }
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Output:
|
2010-05-13 09:49:55 +04:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* "config.h"
|
|
|
|
* "lib"
|
|
|
|
* "main.rb"
|
|
|
|
* ".."
|
|
|
|
* "."
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Encoding:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.foreach('/example') {|entry_name| p entry_name.encoding; break }
|
|
|
|
* Dir.foreach('/example', encoding: 'US-ASCII') {|entry_name| p entry_name.encoding; break }
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Output:
|
|
|
|
*
|
|
|
|
* #<Encoding:UTF-8>
|
|
|
|
* #<Encoding:US-ASCII>
|
|
|
|
*
|
2023-07-18 16:53:24 +03:00
|
|
|
* See {String Encoding}[rdoc-ref:encodings.rdoc@String+Encoding].
|
2023-07-07 23:37:36 +03:00
|
|
|
*
|
|
|
|
* Returns an enumerator if no block is given.
|
2003-12-19 18:18:09 +03:00
|
|
|
*/
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE
|
2008-06-17 02:29:05 +04:00
|
|
|
dir_foreach(int argc, VALUE *argv, VALUE io)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
VALUE dir;
|
|
|
|
|
2008-06-17 02:29:05 +04:00
|
|
|
RETURN_ENUMERATOR(io, argc, argv);
|
|
|
|
dir = dir_open_dir(argc, argv);
|
2000-06-12 11:48:31 +04:00
|
|
|
rb_ensure(dir_each, dir, dir_close, dir);
|
|
|
|
return Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2017-05-25 04:46:36 +03:00
|
|
|
static VALUE
|
|
|
|
dir_collect(VALUE dir)
|
|
|
|
{
|
|
|
|
VALUE ary = rb_ary_new();
|
2017-05-25 05:50:21 +03:00
|
|
|
dir_each_entry(dir, rb_ary_push, ary, FALSE);
|
2017-05-25 04:46:36 +03:00
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
2003-12-19 18:18:09 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.entries(dirname, encoding: 'UTF-8') -> array
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Returns an array of the entry names in the directory at +dirpath+;
|
|
|
|
* sets the given encoding onto each returned entry name:
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.entries('/example') # => ["config.h", "lib", "main.rb", "..", "."]
|
|
|
|
* Dir.entries('/example').first.encoding
|
|
|
|
* # => #<Encoding:UTF-8>
|
|
|
|
* Dir.entries('/example', encoding: 'US-ASCII').first.encoding
|
|
|
|
* # => #<Encoding:US-ASCII>
|
2013-07-19 08:40:07 +04:00
|
|
|
*
|
2023-07-18 16:53:24 +03:00
|
|
|
* See {String Encoding}[rdoc-ref:encodings.rdoc@String+Encoding].
|
2003-12-19 18:18:09 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Raises an exception if the directory does not exist.
|
2003-12-19 18:18:09 +03:00
|
|
|
*/
|
1999-01-20 07:59:39 +03:00
|
|
|
static VALUE
|
2008-06-17 02:29:05 +04:00
|
|
|
dir_entries(int argc, VALUE *argv, VALUE io)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE dir;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-06-17 02:29:05 +04:00
|
|
|
dir = dir_open_dir(argc, argv);
|
2017-05-25 04:46:36 +03:00
|
|
|
return rb_ensure(dir_collect, dir, dir_close, dir);
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2017-05-25 05:50:21 +03:00
|
|
|
static VALUE
|
|
|
|
dir_each_child(VALUE dir)
|
|
|
|
{
|
|
|
|
return dir_each_entry(dir, dir_yield, Qnil, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.each_child(dirpath) {|entry_name| ... } -> nil
|
|
|
|
* Dir.each_child(dirpath, encoding: 'UTF-8') {|entry_name| ... } -> nil
|
2017-05-25 05:50:21 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Like Dir.foreach, except that entries <tt>'.'</tt> and <tt>'..'</tt>
|
|
|
|
* are not included.
|
2017-05-25 05:50:21 +03:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
dir_s_each_child(int argc, VALUE *argv, VALUE io)
|
|
|
|
{
|
|
|
|
VALUE dir;
|
|
|
|
|
|
|
|
RETURN_ENUMERATOR(io, argc, argv);
|
|
|
|
dir = dir_open_dir(argc, argv);
|
|
|
|
rb_ensure(dir_each_child, dir, dir_close, dir);
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2018-02-23 05:18:52 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* each_child {|entry_name| ... } -> self
|
2018-02-23 05:18:52 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Calls the block with each entry name in +self+
|
|
|
|
* except <tt>'.'</tt> and <tt>'..'</tt>:
|
2018-02-23 05:18:52 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* dir = Dir.new('/example')
|
|
|
|
* dir.each_child {|entry_name| p entry_name }
|
2018-02-23 05:18:52 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Output:
|
2018-02-23 05:18:52 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* "config.h"
|
|
|
|
* "lib"
|
|
|
|
* "main.rb"
|
2018-02-23 05:18:52 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* If no block is given, returns an enumerator.
|
2023-09-27 10:18:05 +03:00
|
|
|
*/
|
2018-01-24 10:15:55 +03:00
|
|
|
static VALUE
|
|
|
|
dir_each_child_m(VALUE dir)
|
|
|
|
{
|
|
|
|
RETURN_ENUMERATOR(dir, 0, 0);
|
|
|
|
return dir_each_entry(dir, dir_yield, Qnil, TRUE);
|
|
|
|
}
|
|
|
|
|
2018-02-23 05:18:52 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* children -> array
|
2018-02-23 05:18:52 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Returns an array of the entry names in +self+
|
|
|
|
* except for <tt>'.'</tt> and <tt>'..'</tt>:
|
2018-02-23 05:18:52 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* dir = Dir.new('/example')
|
|
|
|
* dir.children # => ["config.h", "lib", "main.rb"]
|
2018-02-23 05:18:52 +03:00
|
|
|
*
|
|
|
|
*/
|
2017-05-25 05:50:21 +03:00
|
|
|
static VALUE
|
|
|
|
dir_collect_children(VALUE dir)
|
|
|
|
{
|
|
|
|
VALUE ary = rb_ary_new();
|
|
|
|
dir_each_entry(dir, rb_ary_push, ary, TRUE);
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.children(dirpath) -> array
|
|
|
|
* Dir.children(dirpath, encoding: 'UTF-8') -> array
|
2017-05-25 05:50:21 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Returns an array of the entry names in the directory at +dirpath+
|
|
|
|
* except for <tt>'.'</tt> and <tt>'..'</tt>;
|
|
|
|
* sets the given encoding onto each returned entry name:
|
2017-05-25 05:50:21 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.children('/example') # => ["config.h", "lib", "main.rb"]
|
|
|
|
* Dir.children('/example').first.encoding
|
|
|
|
* # => #<Encoding:UTF-8>
|
|
|
|
* Dir.children('/example', encoding: 'US-ASCII').first.encoding
|
|
|
|
* # => #<Encoding:US-ASCII>
|
2017-05-25 05:50:21 +03:00
|
|
|
*
|
2023-07-18 16:53:24 +03:00
|
|
|
* See {String Encoding}[rdoc-ref:encodings.rdoc@String+Encoding].
|
2017-05-25 05:50:21 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Raises an exception if the directory does not exist.
|
2017-05-25 05:50:21 +03:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
dir_s_children(int argc, VALUE *argv, VALUE io)
|
|
|
|
{
|
|
|
|
VALUE dir;
|
|
|
|
|
|
|
|
dir = dir_open_dir(argc, argv);
|
|
|
|
return rb_ensure(dir_collect_children, dir, dir_close, dir);
|
|
|
|
}
|
|
|
|
|
2012-11-04 05:19:11 +04:00
|
|
|
static int
|
|
|
|
fnmatch_brace(const char *pattern, VALUE val, void *enc)
|
|
|
|
{
|
|
|
|
struct brace_args *arg = (struct brace_args *)val;
|
|
|
|
VALUE path = arg->value;
|
2013-02-23 04:48:44 +04:00
|
|
|
rb_encoding *enc_pattern = enc;
|
|
|
|
rb_encoding *enc_path = rb_enc_get(path);
|
2012-11-04 05:19:11 +04:00
|
|
|
|
2013-02-23 04:48:44 +04:00
|
|
|
if (enc_pattern != enc_path) {
|
|
|
|
if (!rb_enc_asciicompat(enc_pattern))
|
|
|
|
return FNM_NOMATCH;
|
|
|
|
if (!rb_enc_asciicompat(enc_path))
|
|
|
|
return FNM_NOMATCH;
|
|
|
|
if (!rb_enc_str_asciionly_p(path)) {
|
|
|
|
int cr = ENC_CODERANGE_7BIT;
|
|
|
|
long len = strlen(pattern);
|
|
|
|
if (rb_str_coderange_scan_restartable(pattern, pattern + len,
|
|
|
|
enc_pattern, &cr) != len)
|
|
|
|
return FNM_NOMATCH;
|
|
|
|
if (cr != ENC_CODERANGE_7BIT)
|
|
|
|
return FNM_NOMATCH;
|
|
|
|
}
|
|
|
|
}
|
2012-11-04 05:19:11 +04:00
|
|
|
return (fnmatch(pattern, enc, RSTRING_PTR(path), arg->flags) == 0);
|
|
|
|
}
|
|
|
|
|
2021-05-20 16:57:33 +03:00
|
|
|
/* :nodoc: */
|
2001-06-13 14:51:39 +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
|
|
|
file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
|
2001-06-13 14:51:39 +04:00
|
|
|
{
|
|
|
|
VALUE pattern, path;
|
|
|
|
VALUE rflags;
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
|
|
|
|
flags = NUM2INT(rflags);
|
|
|
|
else
|
|
|
|
flags = 0;
|
|
|
|
|
2018-12-12 08:38:09 +03:00
|
|
|
StringValueCStr(pattern);
|
2007-12-09 08:12:31 +03:00
|
|
|
FilePathStringValue(path);
|
2001-06-13 14:51:39 +04:00
|
|
|
|
2012-11-04 05:19:11 +04:00
|
|
|
if (flags & FNM_EXTGLOB) {
|
|
|
|
struct brace_args args;
|
|
|
|
|
|
|
|
args.value = path;
|
|
|
|
args.flags = flags;
|
|
|
|
if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
|
2017-07-25 08:55:22 +03:00
|
|
|
(VALUE)&args, rb_enc_get(pattern), pattern) > 0)
|
2012-11-04 05:19:11 +04:00
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
else {
|
2013-02-23 04:48:44 +04:00
|
|
|
rb_encoding *enc = rb_enc_compatible(pattern, path);
|
|
|
|
if (!enc) return Qfalse;
|
|
|
|
if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
|
2012-11-04 05:19:11 +04:00
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
RB_GC_GUARD(pattern);
|
2001-06-13 14:51:39 +04:00
|
|
|
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2009-02-02 10:33:08 +03:00
|
|
|
/*
|
2023-07-07 23:37:36 +03:00
|
|
|
* call-seq:
|
|
|
|
* Dir.home(user_name = nil) -> dirpath
|
2009-02-02 10:33:08 +03:00
|
|
|
*
|
2023-11-14 11:20:57 +03:00
|
|
|
* Retruns the home directory path of the user specified with +user_name+
|
|
|
|
* if it is not +nil+, or the current login user:
|
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.home # => "/home/me"
|
|
|
|
* Dir.home('root') # => "/root"
|
|
|
|
*
|
|
|
|
* Raises ArgumentError if +user_name+ is not a user name.
|
2009-02-02 10:33:08 +03:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
dir_s_home(int argc, VALUE *argv, VALUE obj)
|
|
|
|
{
|
|
|
|
VALUE user;
|
|
|
|
const char *u = 0;
|
|
|
|
|
2013-07-25 08:06:50 +04:00
|
|
|
rb_check_arity(argc, 0, 1);
|
2013-07-25 08:16:08 +04:00
|
|
|
user = (argc > 0) ? argv[0] : Qnil;
|
2009-02-02 10:33:08 +03:00
|
|
|
if (!NIL_P(user)) {
|
2024-01-09 22:04:20 +03:00
|
|
|
StringValue(user);
|
2013-07-25 08:06:50 +04:00
|
|
|
rb_must_asciicompat(user);
|
2009-02-02 10:33:08 +03:00
|
|
|
u = StringValueCStr(user);
|
2013-07-25 08:06:50 +04:00
|
|
|
if (*u) {
|
|
|
|
return rb_home_dir_of(user, rb_str_new(0, 0));
|
|
|
|
}
|
2009-02-02 10:33:08 +03:00
|
|
|
}
|
2013-07-25 08:06:50 +04:00
|
|
|
return rb_default_home_dir(rb_str_new(0, 0));
|
|
|
|
|
2009-02-02 10:33:08 +03:00
|
|
|
}
|
|
|
|
|
2012-06-17 17:23:56 +04:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.exist?(dirpath) -> true or false
|
|
|
|
*
|
|
|
|
* Returns whether +dirpath+ is a directory in the underlying file system:
|
|
|
|
*
|
|
|
|
* Dir.exist?('/example') # => true
|
|
|
|
* Dir.exist?('/nosuch') # => false
|
|
|
|
* Dir.exist?('/example/main.rb') # => false
|
2012-06-17 17:23:56 +04:00
|
|
|
*
|
2023-11-14 11:29:15 +03:00
|
|
|
* Same as File.directory?.
|
2012-06-17 17:23:56 +04:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
VALUE
|
2014-09-30 09:25:32 +04:00
|
|
|
rb_file_directory_p(void)
|
2012-06-17 17:23:56 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-10-04 03:04:51 +03:00
|
|
|
static void *
|
|
|
|
nogvl_dir_empty_p(void *ptr)
|
|
|
|
{
|
|
|
|
const char *path = ptr;
|
|
|
|
DIR *dir = opendir(path);
|
|
|
|
struct dirent *dp;
|
|
|
|
VALUE result = Qtrue;
|
|
|
|
|
|
|
|
if (!dir) {
|
|
|
|
int e = errno;
|
2017-11-18 05:01:49 +03:00
|
|
|
switch (gc_for_fd_with_gvl(e)) {
|
2017-10-04 03:04:51 +03:00
|
|
|
default:
|
|
|
|
dir = opendir(path);
|
|
|
|
if (dir) break;
|
|
|
|
e = errno;
|
|
|
|
/* fall through */
|
|
|
|
case 0:
|
|
|
|
if (e == ENOTDIR) return (void *)Qfalse;
|
2023-05-12 04:57:42 +03:00
|
|
|
return (void *)INT2FIX(e);
|
2017-10-04 03:04:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
while ((dp = READDIR(dir, NULL)) != NULL) {
|
|
|
|
if (!to_be_skipped(dp)) {
|
|
|
|
result = Qfalse;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir(dir);
|
|
|
|
return (void *)result;
|
|
|
|
}
|
|
|
|
|
2016-02-16 11:34:47 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2023-07-07 23:37:36 +03:00
|
|
|
* Dir.empty?(dirpath) -> true or false
|
|
|
|
*
|
|
|
|
* Returns whether +dirpath+ specifies an empty directory:
|
|
|
|
*
|
|
|
|
* dirpath = '/tmp/foo'
|
|
|
|
* Dir.mkdir(dirpath)
|
|
|
|
* Dir.empty?(dirpath) # => true
|
|
|
|
* Dir.empty?('/example') # => false
|
|
|
|
* Dir.empty?('/example/main.rb') # => false
|
2016-02-16 11:34:47 +03:00
|
|
|
*
|
2023-07-07 23:37:36 +03:00
|
|
|
* Raises an exception if +dirpath+ does not specify a directory or file
|
|
|
|
* in the underlying file system.
|
2016-02-16 11:34:47 +03:00
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
rb_dir_s_empty_p(VALUE obj, VALUE dirname)
|
|
|
|
{
|
2017-10-04 03:04:51 +03:00
|
|
|
VALUE result, orig;
|
2016-02-16 11:34:47 +03:00
|
|
|
const char *path;
|
|
|
|
enum {false_on_notdir = 1};
|
|
|
|
|
2018-03-28 12:58:52 +03:00
|
|
|
FilePathValue(dirname);
|
2016-02-16 11:34:47 +03:00
|
|
|
orig = rb_str_dup_frozen(dirname);
|
|
|
|
dirname = rb_str_encode_ospath(dirname);
|
|
|
|
dirname = rb_str_dup_frozen(dirname);
|
|
|
|
path = RSTRING_PTR(dirname);
|
|
|
|
|
|
|
|
#if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT
|
|
|
|
{
|
|
|
|
u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
|
|
|
|
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
|
|
|
|
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) != 0)
|
|
|
|
rb_sys_fail_path(orig);
|
|
|
|
if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) {
|
|
|
|
al.commonattr = 0;
|
|
|
|
al.dirattr = ATTR_DIR_ENTRYCOUNT;
|
|
|
|
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) == 0) {
|
|
|
|
if (attrbuf[0] >= 2 * sizeof(u_int32_t))
|
2022-01-01 09:41:00 +03:00
|
|
|
return RBOOL(attrbuf[1] == 0);
|
2016-02-16 11:34:47 +03:00
|
|
|
if (false_on_notdir) return Qfalse;
|
|
|
|
}
|
|
|
|
rb_sys_fail_path(orig);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-01-24 14:51:50 +03:00
|
|
|
result = (VALUE)IO_WITHOUT_GVL(nogvl_dir_empty_p, (void *)path);
|
2023-05-12 04:57:42 +03:00
|
|
|
if (FIXNUM_P(result)) {
|
|
|
|
rb_syserr_fail_path((int)FIX2LONG(result), orig);
|
2016-02-16 11:34:47 +03:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +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_Dir(void)
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
2024-02-07 13:51:30 +03:00
|
|
|
rb_gc_register_address(&chdir_lock.path);
|
2024-02-14 11:56:14 +03:00
|
|
|
rb_gc_register_address(&chdir_lock.thread);
|
2024-02-07 13:51:30 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_cDir = rb_define_class("Dir", rb_cObject);
|
|
|
|
|
|
|
|
rb_include_module(rb_cDir, rb_mEnumerable);
|
|
|
|
|
2002-12-20 11:33:17 +03:00
|
|
|
rb_define_alloc_func(rb_cDir, dir_s_alloc);
|
2023-02-10 00:34:37 +03:00
|
|
|
rb_define_singleton_method(rb_cDir,"for_fd", dir_s_for_fd, 1);
|
2008-06-17 19:05:50 +04:00
|
|
|
rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, -1);
|
2008-06-17 02:29:05 +04:00
|
|
|
rb_define_singleton_method(rb_cDir, "entries", dir_entries, -1);
|
2017-05-25 05:50:21 +03:00
|
|
|
rb_define_singleton_method(rb_cDir, "each_child", dir_s_each_child, -1);
|
|
|
|
rb_define_singleton_method(rb_cDir, "children", dir_s_children, -1);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2014-09-04 19:54:04 +04:00
|
|
|
rb_define_method(rb_cDir,"fileno", dir_fileno, 0);
|
2001-09-19 10:54:11 +04:00
|
|
|
rb_define_method(rb_cDir,"path", dir_path, 0);
|
2009-09-04 03:07:13 +04:00
|
|
|
rb_define_method(rb_cDir,"to_path", dir_path, 0);
|
2004-01-10 16:46:21 +03:00
|
|
|
rb_define_method(rb_cDir,"inspect", dir_inspect, 0);
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_method(rb_cDir,"read", dir_read, 0);
|
|
|
|
rb_define_method(rb_cDir,"each", dir_each, 0);
|
2018-01-24 10:15:55 +03:00
|
|
|
rb_define_method(rb_cDir,"each_child", dir_each_child_m, 0);
|
|
|
|
rb_define_method(rb_cDir,"children", dir_collect_children, 0);
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_method(rb_cDir,"rewind", dir_rewind, 0);
|
|
|
|
rb_define_method(rb_cDir,"tell", dir_tell, 0);
|
|
|
|
rb_define_method(rb_cDir,"seek", dir_seek, 1);
|
2000-06-12 11:48:31 +04:00
|
|
|
rb_define_method(rb_cDir,"pos", dir_tell, 0);
|
2002-01-21 10:44:06 +03:00
|
|
|
rb_define_method(rb_cDir,"pos=", dir_set_pos, 1);
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_method(rb_cDir,"close", dir_close, 0);
|
2023-02-09 23:45:52 +03:00
|
|
|
rb_define_method(rb_cDir,"chdir", dir_chdir, 0);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2023-01-17 00:29:43 +03:00
|
|
|
rb_define_singleton_method(rb_cDir,"fchdir", dir_s_fchdir, 1);
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_singleton_method(rb_cDir,"chdir", dir_s_chdir, -1);
|
|
|
|
rb_define_singleton_method(rb_cDir,"getwd", dir_s_getwd, 0);
|
|
|
|
rb_define_singleton_method(rb_cDir,"pwd", dir_s_getwd, 0);
|
|
|
|
rb_define_singleton_method(rb_cDir,"chroot", dir_s_chroot, 1);
|
|
|
|
rb_define_singleton_method(rb_cDir,"mkdir", dir_s_mkdir, -1);
|
|
|
|
rb_define_singleton_method(rb_cDir,"rmdir", dir_s_rmdir, 1);
|
|
|
|
rb_define_singleton_method(rb_cDir,"delete", dir_s_rmdir, 1);
|
|
|
|
rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
|
2009-02-02 10:33:08 +03:00
|
|
|
rb_define_singleton_method(rb_cDir,"home", dir_s_home, -1);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2012-06-17 17:23:56 +04:00
|
|
|
rb_define_singleton_method(rb_cDir,"exist?", rb_file_directory_p, 1);
|
2016-02-16 11:34:47 +03:00
|
|
|
rb_define_singleton_method(rb_cDir,"empty?", rb_dir_s_empty_p, 1);
|
2001-06-13 14:51:39 +04:00
|
|
|
|
|
|
|
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
|
|
|
|
rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
|
2023-12-18 13:43:52 +03:00
|
|
|
|
|
|
|
/* Document-const: FNM_NOESCAPE
|
|
|
|
* {File::FNM_NOESCAPE}[rdoc-ref:File::Constants@File-3A-3AFNM_NOESCAPE] */
|
2001-06-13 14:51:39 +04:00
|
|
|
rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
|
2023-12-18 13:43:52 +03:00
|
|
|
/* Document-const: FNM_PATHNAME
|
|
|
|
* {File::FNM_PATHNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_PATHNAME] */
|
2001-06-13 14:51:39 +04:00
|
|
|
rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
|
2023-12-18 13:43:52 +03:00
|
|
|
/* Document-const: FNM_DOTMATCH
|
|
|
|
* {File::FNM_DOTMATCH}[rdoc-ref:File::Constants@File-3A-3AFNM_DOTMATCH] */
|
2002-03-13 13:11:09 +03:00
|
|
|
rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
|
2023-12-18 13:43:52 +03:00
|
|
|
/* Document-const: FNM_CASEFOLD
|
|
|
|
* {File::FNM_CASEFOLD}[rdoc-ref:File::Constants@File-3A-3AFNM_CASEFOLD] */
|
2001-06-13 14:51:39 +04:00
|
|
|
rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
|
2023-12-18 13:43:52 +03:00
|
|
|
/* Document-const: FNM_EXTGLOB
|
|
|
|
* {File::FNM_EXTGLOB}[rdoc-ref:File::Constants@File-3A-3AFNM_EXTGLOB] */
|
2012-11-04 05:19:11 +04:00
|
|
|
rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB));
|
2023-12-18 13:43:52 +03:00
|
|
|
/* Document-const: FNM_SYSCASE
|
|
|
|
* {File::FNM_SYSCASE}[rdoc-ref:File::Constants@File-3A-3AFNM_SYSCASE] */
|
2005-12-14 17:40:14 +03:00
|
|
|
rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
|
2023-12-18 13:43:52 +03:00
|
|
|
/* Document-const: FNM_SHORTNAME
|
|
|
|
* {File::FNM_SHORTNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_SHORTNAME] */
|
2015-06-04 01:12:24 +03:00
|
|
|
rb_file_const("FNM_SHORTNAME", INT2FIX(FNM_SHORTNAME));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2020-01-18 07:59:21 +03:00
|
|
|
|
|
|
|
#include "dir.rbinc"
|