Ruby  2.1.10p492(2016-04-01revision54464)
dir.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  dir.c -
4 
5  $Author: nagachika $
6  created at: Wed Jan 5 09:51:01 JST 1994
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9  Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10  Copyright (C) 2000 Information-technology Promotion Agency, Japan
11 
12 **********************************************************************/
13 
14 #include "ruby/ruby.h"
15 #include "ruby/encoding.h"
16 #include "internal.h"
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24 
25 #if defined HAVE_DIRENT_H && !defined _WIN32
26 # include <dirent.h>
27 # define NAMLEN(dirent) strlen((dirent)->d_name)
28 #elif defined HAVE_DIRECT_H && !defined _WIN32
29 # include <direct.h>
30 # define NAMLEN(dirent) strlen((dirent)->d_name)
31 #else
32 # define dirent direct
33 # define NAMLEN(dirent) (dirent)->d_namlen
34 # if HAVE_SYS_NDIR_H
35 # include <sys/ndir.h>
36 # endif
37 # if HAVE_SYS_DIR_H
38 # include <sys/dir.h>
39 # endif
40 # if HAVE_NDIR_H
41 # include <ndir.h>
42 # endif
43 # ifdef _WIN32
44 # include "win32/dir.h"
45 # endif
46 #endif
47 #if defined(__native_client__) && defined(NACL_NEWLIB)
48 # include "nacl/dirent.h"
49 # include "nacl/stat.h"
50 #endif
51 
52 #include <errno.h>
53 
54 #ifndef HAVE_STDLIB_H
55 char *getenv();
56 #endif
57 
58 #ifndef HAVE_STRING_H
59 char *strchr(char*,char);
60 #endif
61 
62 #include <ctype.h>
63 
64 #include "ruby/util.h"
65 
66 /* define system APIs */
67 #ifdef _WIN32
68 #undef chdir
69 #define chdir(p) rb_w32_uchdir(p)
70 #undef mkdir
71 #define mkdir(p, m) rb_w32_umkdir((p), (m))
72 #undef rmdir
73 #define rmdir(p) rb_w32_urmdir(p)
74 #undef opendir
75 #define opendir(p) rb_w32_uopendir(p)
76 #endif
77 
78 #ifdef __APPLE__
79 # define HAVE_HFS 1
80 #else
81 # define HAVE_HFS 0
82 #endif
83 #if HAVE_HFS
84 #include <sys/param.h>
85 #include <sys/mount.h>
86 
87 static inline int
88 is_hfs(DIR *dirp)
89 {
90  struct statfs buf;
91  if (fstatfs(dirfd(dirp), &buf) == 0) {
92  return buf.f_type == 17; /* HFS on darwin */
93  }
94  return FALSE;
95 }
96 
97 static inline int
98 has_nonascii(const char *ptr, size_t len)
99 {
100  while (len > 0) {
101  if (!ISASCII(*ptr)) return 1;
102  ptr++;
103  --len;
104  }
105  return 0;
106 }
107 
108 # define IF_HAVE_HFS(something) something
109 #else
110 # define IF_HAVE_HFS(something) /* nothing */
111 #endif
112 
113 #define FNM_NOESCAPE 0x01
114 #define FNM_PATHNAME 0x02
115 #define FNM_DOTMATCH 0x04
116 #define FNM_CASEFOLD 0x08
117 #define FNM_EXTGLOB 0x10
118 #if CASEFOLD_FILESYSTEM
119 #define FNM_SYSCASE FNM_CASEFOLD
120 #else
121 #define FNM_SYSCASE 0
122 #endif
123 
124 #define FNM_NOMATCH 1
125 #define FNM_ERROR 2
126 
127 # define Next(p, e, enc) ((p)+ rb_enc_mbclen((p), (e), (enc)))
128 # define Inc(p, e, enc) ((p) = Next((p), (e), (enc)))
129 
130 static char *
132  const char *p, /* pattern (next to '[') */
133  const char *pend,
134  const char *s, /* string */
135  const char *send,
136  int flags,
137  rb_encoding *enc)
138 {
139  const int nocase = flags & FNM_CASEFOLD;
140  const int escape = !(flags & FNM_NOESCAPE);
141  unsigned int c1, c2;
142  int r;
143  int ok = 0, not = 0;
144 
145  if (p >= pend) return NULL;
146  if (*p == '!' || *p == '^') {
147  not = 1;
148  p++;
149  }
150 
151  while (*p != ']') {
152  const char *t1 = p;
153  if (escape && *t1 == '\\')
154  t1++;
155  if (!*t1)
156  return NULL;
157  p = t1 + (r = rb_enc_mbclen(t1, pend, enc));
158  if (p >= pend) return NULL;
159  if (p[0] == '-' && p[1] != ']') {
160  const char *t2 = p + 1;
161  int r2;
162  if (escape && *t2 == '\\')
163  t2++;
164  if (!*t2)
165  return NULL;
166  p = t2 + (r2 = rb_enc_mbclen(t2, pend, enc));
167  if (ok) continue;
168  if ((r <= (send-s) && memcmp(t1, s, r) == 0) ||
169  (r2 <= (send-s) && memcmp(t2, s, r2) == 0)) {
170  ok = 1;
171  continue;
172  }
173  c1 = rb_enc_codepoint(s, send, enc);
174  if (nocase) c1 = rb_enc_toupper(c1, enc);
175  c2 = rb_enc_codepoint(t1, pend, enc);
176  if (nocase) c2 = rb_enc_toupper(c2, enc);
177  if (c1 < c2) continue;
178  c2 = rb_enc_codepoint(t2, pend, enc);
179  if (nocase) c2 = rb_enc_toupper(c2, enc);
180  if (c1 > c2) continue;
181  }
182  else {
183  if (ok) continue;
184  if (r <= (send-s) && memcmp(t1, s, r) == 0) {
185  ok = 1;
186  continue;
187  }
188  if (!nocase) continue;
189  c1 = rb_enc_toupper(rb_enc_codepoint(s, send, enc), enc);
190  c2 = rb_enc_toupper(rb_enc_codepoint(p, pend, enc), enc);
191  if (c1 != c2) continue;
192  }
193  ok = 1;
194  }
195 
196  return ok == not ? NULL : (char *)p + 1;
197 }
198 
199 /* If FNM_PATHNAME is set, only path element will be matched. (upto '/' or '\0')
200  Otherwise, entire string will be matched.
201  End marker itself won't be compared.
202  And if function succeeds, *pcur reaches end marker.
203 */
204 #define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p))
205 #define ISEND(p) (!*(p) || (pathname && *(p) == '/'))
206 #define RETURN(val) return *pcur = p, *scur = s, (val);
207 
208 static int
210  const char **pcur, /* pattern */
211  const char **scur, /* string */
212  int flags,
213  rb_encoding *enc)
214 {
215  const int period = !(flags & FNM_DOTMATCH);
216  const int pathname = flags & FNM_PATHNAME;
217  const int escape = !(flags & FNM_NOESCAPE);
218  const int nocase = flags & FNM_CASEFOLD;
219 
220  const char *ptmp = 0;
221  const char *stmp = 0;
222 
223  const char *p = *pcur;
224  const char *pend = p + strlen(p);
225  const char *s = *scur;
226  const char *send = s + strlen(s);
227 
228  int r;
229 
230  if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
232 
233  while (1) {
234  switch (*p) {
235  case '*':
236  do { p++; } while (*p == '*');
237  if (ISEND(UNESCAPE(p))) {
238  p = UNESCAPE(p);
239  RETURN(0);
240  }
241  if (ISEND(s))
243  ptmp = p;
244  stmp = s;
245  continue;
246 
247  case '?':
248  if (ISEND(s))
250  p++;
251  Inc(s, send, enc);
252  continue;
253 
254  case '[': {
255  const char *t;
256  if (ISEND(s))
258  if ((t = bracket(p + 1, pend, s, send, flags, enc)) != 0) {
259  p = t;
260  Inc(s, send, enc);
261  continue;
262  }
263  goto failed;
264  }
265  }
266 
267  /* ordinary */
268  p = UNESCAPE(p);
269  if (ISEND(s))
270  RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
271  if (ISEND(p))
272  goto failed;
273  r = rb_enc_precise_mbclen(p, pend, enc);
274  if (!MBCLEN_CHARFOUND_P(r))
275  goto failed;
276  if (r <= (send-s) && memcmp(p, s, r) == 0) {
277  p += r;
278  s += r;
279  continue;
280  }
281  if (!nocase) goto failed;
282  if (rb_enc_toupper(rb_enc_codepoint(p, pend, enc), enc) !=
283  rb_enc_toupper(rb_enc_codepoint(s, send, enc), enc))
284  goto failed;
285  p += r;
286  Inc(s, send, enc);
287  continue;
288 
289  failed: /* try next '*' position */
290  if (ptmp && stmp) {
291  p = ptmp;
292  Inc(stmp, send, enc); /* !ISEND(*stmp) */
293  s = stmp;
294  continue;
295  }
297  }
298 }
299 
300 static int
302  const char *pattern,
303  rb_encoding *enc,
304  const char *string,
305  int flags)
306 {
307  const char *p = pattern;
308  const char *s = string;
309  const char *send = s + strlen(string);
310  const int period = !(flags & FNM_DOTMATCH);
311  const int pathname = flags & FNM_PATHNAME;
312 
313  const char *ptmp = 0;
314  const char *stmp = 0;
315 
316  if (pathname) {
317  while (1) {
318  if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
319  do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
320  ptmp = p;
321  stmp = s;
322  }
323  if (fnmatch_helper(&p, &s, flags, enc) == 0) {
324  while (*s && *s != '/') Inc(s, send, enc);
325  if (*p && *s) {
326  p++;
327  s++;
328  continue;
329  }
330  if (!*p && !*s)
331  return 0;
332  }
333  /* failed : try next recursion */
334  if (ptmp && stmp && !(period && *stmp == '.')) {
335  while (*stmp && *stmp != '/') Inc(stmp, send, enc);
336  if (*stmp) {
337  p = ptmp;
338  stmp++;
339  s = stmp;
340  continue;
341  }
342  }
343  return FNM_NOMATCH;
344  }
345  }
346  else
347  return fnmatch_helper(&p, &s, flags, enc);
348 }
349 
351 
352 struct dir_data {
356 };
357 
358 static void
359 dir_mark(void *ptr)
360 {
361  struct dir_data *dir = ptr;
362  rb_gc_mark(dir->path);
363 }
364 
365 static void
366 dir_free(void *ptr)
367 {
368  struct dir_data *dir = ptr;
369  if (dir) {
370  if (dir->dir) closedir(dir->dir);
371  }
372  xfree(dir);
373 }
374 
375 static size_t
376 dir_memsize(const void *ptr)
377 {
378  return ptr ? sizeof(struct dir_data) : 0;
379 }
380 
382  "dir",
385 };
386 
387 static VALUE dir_close(VALUE);
388 
389 #define GlobPathValue(str, safe) \
390  /* can contain null bytes as separators */ \
391  (!RB_TYPE_P((str), T_STRING) ? \
392  (void)FilePathValue(str) : \
393  (void)(check_safe_glob((str), (safe)), \
394  check_glob_encoding(str), (str)))
395 #define check_safe_glob(str, safe) ((safe) ? rb_check_safe_obj(str) : (void)0)
396 #define check_glob_encoding(str) rb_enc_check((str), rb_enc_from_encoding(rb_usascii_encoding()))
397 
398 static VALUE
400 {
401  struct dir_data *dirp;
402  VALUE obj = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dirp);
403 
404  dirp->dir = NULL;
405  dirp->path = Qnil;
406  dirp->enc = NULL;
407 
408  return obj;
409 }
410 
411 /*
412  * call-seq:
413  * Dir.new( string ) -> aDir
414  * Dir.new( string, encoding: enc ) -> aDir
415  *
416  * Returns a new directory object for the named directory.
417  *
418  * The optional <i>enc</i> argument specifies the encoding of the directory.
419  * If not specified, the filesystem encoding is used.
420  */
421 static VALUE
423 {
424  struct dir_data *dp;
425  rb_encoding *fsenc;
426  VALUE dirname, opt, orig;
427  static ID keyword_ids[1];
428 
429  if (!keyword_ids[0]) {
430  keyword_ids[0] = rb_intern("encoding");
431  }
432 
433  fsenc = rb_filesystem_encoding();
434 
435  rb_scan_args(argc, argv, "1:", &dirname, &opt);
436 
437  if (!NIL_P(opt)) {
438  VALUE enc;
439  rb_get_kwargs(opt, keyword_ids, 0, 1, &enc);
440  if (enc != Qundef && !NIL_P(enc)) {
441  fsenc = rb_to_encoding(enc);
442  }
443  }
444 
445  GlobPathValue(dirname, FALSE);
446  orig = rb_str_dup_frozen(dirname);
447  dirname = rb_str_encode_ospath(dirname);
448  dirname = rb_str_dup_frozen(dirname);
449 
451  if (dp->dir) closedir(dp->dir);
452  dp->dir = NULL;
453  dp->path = Qnil;
454  dp->enc = fsenc;
455  dp->dir = opendir(RSTRING_PTR(dirname));
456  if (dp->dir == NULL) {
457  if (errno == EMFILE || errno == ENFILE) {
458  rb_gc();
459  dp->dir = opendir(RSTRING_PTR(dirname));
460  }
461  if (dp->dir == NULL) {
462  rb_sys_fail_path(orig);
463  }
464  }
465  dp->path = orig;
466 
467  return dir;
468 }
469 
470 /*
471  * call-seq:
472  * Dir.open( string ) -> aDir
473  * Dir.open( string, encoding: enc ) -> aDir
474  * Dir.open( string ) {| aDir | block } -> anObject
475  * Dir.open( string, encoding: enc ) {| aDir | block } -> anObject
476  *
477  * The optional <i>enc</i> argument specifies the encoding of the directory.
478  * If not specified, the filesystem encoding is used.
479  *
480  * With no block, <code>open</code> is a synonym for
481  * <code>Dir::new</code>. If a block is present, it is passed
482  * <i>aDir</i> as a parameter. The directory is closed at the end of
483  * the block, and <code>Dir::open</code> returns the value of the
484  * block.
485  */
486 static VALUE
488 {
489  struct dir_data *dp;
491 
493  if (rb_block_given_p()) {
494  return rb_ensure(rb_yield, dir, dir_close, dir);
495  }
496 
497  return dir;
498 }
499 
500 static void
502 {
503  rb_raise(rb_eIOError, "closed directory");
504 }
505 
506 static struct dir_data *
508 {
509  struct dir_data *dirp;
512  if (!dirp->dir) dir_closed();
513  return dirp;
514 }
515 
516 #define GetDIR(obj, dirp) ((dirp) = dir_check(obj))
517 
518 
519 /*
520  * call-seq:
521  * dir.inspect -> string
522  *
523  * Return a string describing this Dir object.
524  */
525 static VALUE
527 {
528  struct dir_data *dirp;
529 
531  if (!NIL_P(dirp->path)) {
532  VALUE str = rb_str_new_cstr("#<");
534  rb_str_cat2(str, ":");
535  rb_str_append(str, dirp->path);
536  rb_str_cat2(str, ">");
537  return str;
538  }
539  return rb_funcall(dir, rb_intern("to_s"), 0, 0);
540 }
541 
542 /*
543  * call-seq:
544  * dir.path -> string or nil
545  * dir.to_path -> string or nil
546  *
547  * Returns the path parameter passed to <em>dir</em>'s constructor.
548  *
549  * d = Dir.new("..")
550  * d.path #=> ".."
551  */
552 static VALUE
554 {
555  struct dir_data *dirp;
556 
558  if (NIL_P(dirp->path)) return Qnil;
559  return rb_str_dup(dirp->path);
560 }
561 
562 #if defined _WIN32
563 # define READDIR(dir, enc) rb_w32_readdir((dir), (enc))
564 #else
565 # define READDIR(dir, enc) readdir((dir))
566 #endif
567 
568 /*
569  * call-seq:
570  * dir.read -> string or nil
571  *
572  * Reads the next entry from <em>dir</em> and returns it as a string.
573  * Returns <code>nil</code> at the end of the stream.
574  *
575  * d = Dir.new("testdir")
576  * d.read #=> "."
577  * d.read #=> ".."
578  * d.read #=> "config.h"
579  */
580 static VALUE
582 {
583  struct dir_data *dirp;
584  struct dirent *dp;
585 
586  GetDIR(dir, dirp);
587  errno = 0;
588  if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
589  return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
590  }
591  else {
592  if (errno != 0) rb_sys_fail(0);
593  return Qnil; /* end of stream */
594  }
595 }
596 
597 /*
598  * call-seq:
599  * dir.each { |filename| block } -> dir
600  * dir.each -> an_enumerator
601  *
602  * Calls the block once for each entry in this directory, passing the
603  * filename of each entry as a parameter to the block.
604  *
605  * If no block is given, an enumerator is returned instead.
606  *
607  * d = Dir.new("testdir")
608  * d.each {|x| puts "Got #{x}" }
609  *
610  * <em>produces:</em>
611  *
612  * Got .
613  * Got ..
614  * Got config.h
615  * Got main.rb
616  */
617 static VALUE
619 {
620  struct dir_data *dirp;
621  struct dirent *dp;
622  IF_HAVE_HFS(int hfs_p);
623 
624  RETURN_ENUMERATOR(dir, 0, 0);
625  GetDIR(dir, dirp);
626  rewinddir(dirp->dir);
627  IF_HAVE_HFS(hfs_p = is_hfs(dirp->dir));
628  while ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
629  const char *name = dp->d_name;
630  size_t namlen = NAMLEN(dp);
631  VALUE path;
632 #if HAVE_HFS
633  if (hfs_p && has_nonascii(name, namlen) &&
634  !NIL_P(path = rb_str_normalize_ospath(name, namlen))) {
635  path = rb_external_str_with_enc(path, dirp->enc);
636  }
637  else
638 #endif
639  path = rb_external_str_new_with_enc(name, namlen, dirp->enc);
640  rb_yield(path);
641  if (dirp->dir == NULL) dir_closed();
642  }
643  return dir;
644 }
645 
646 #ifdef HAVE_TELLDIR
647 /*
648  * call-seq:
649  * dir.pos -> integer
650  * dir.tell -> integer
651  *
652  * Returns the current position in <em>dir</em>. See also
653  * <code>Dir#seek</code>.
654  *
655  * d = Dir.new("testdir")
656  * d.tell #=> 0
657  * d.read #=> "."
658  * d.tell #=> 12
659  */
660 static VALUE
661 dir_tell(VALUE dir)
662 {
663  struct dir_data *dirp;
664  long pos;
665 
666  GetDIR(dir, dirp);
667  pos = telldir(dirp->dir);
668  return rb_int2inum(pos);
669 }
670 #else
671 #define dir_tell rb_f_notimplement
672 #endif
673 
674 #ifdef HAVE_SEEKDIR
675 /*
676  * call-seq:
677  * dir.seek( integer ) -> dir
678  *
679  * Seeks to a particular location in <em>dir</em>. <i>integer</i>
680  * must be a value returned by <code>Dir#tell</code>.
681  *
682  * d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
683  * d.read #=> "."
684  * i = d.tell #=> 12
685  * d.read #=> ".."
686  * d.seek(i) #=> #<Dir:0x401b3c40>
687  * d.read #=> ".."
688  */
689 static VALUE
690 dir_seek(VALUE dir, VALUE pos)
691 {
692  struct dir_data *dirp;
693  long p = NUM2LONG(pos);
694 
695  GetDIR(dir, dirp);
696  seekdir(dirp->dir, p);
697  return dir;
698 }
699 #else
700 #define dir_seek rb_f_notimplement
701 #endif
702 
703 #ifdef HAVE_SEEKDIR
704 /*
705  * call-seq:
706  * dir.pos = integer -> integer
707  *
708  * Synonym for <code>Dir#seek</code>, but returns the position
709  * parameter.
710  *
711  * d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
712  * d.read #=> "."
713  * i = d.pos #=> 12
714  * d.read #=> ".."
715  * d.pos = i #=> 12
716  * d.read #=> ".."
717  */
718 static VALUE
720 {
721  dir_seek(dir, pos);
722  return pos;
723 }
724 #else
725 #define dir_set_pos rb_f_notimplement
726 #endif
727 
728 /*
729  * call-seq:
730  * dir.rewind -> dir
731  *
732  * Repositions <em>dir</em> to the first entry.
733  *
734  * d = Dir.new("testdir")
735  * d.read #=> "."
736  * d.rewind #=> #<Dir:0x401b3fb0>
737  * d.read #=> "."
738  */
739 static VALUE
741 {
742  struct dir_data *dirp;
743 
744  GetDIR(dir, dirp);
745  rewinddir(dirp->dir);
746  return dir;
747 }
748 
749 /*
750  * call-seq:
751  * dir.close -> nil
752  *
753  * Closes the directory stream. Any further attempts to access
754  * <em>dir</em> will raise an <code>IOError</code>.
755  *
756  * d = Dir.new("testdir")
757  * d.close #=> nil
758  */
759 static VALUE
761 {
762  struct dir_data *dirp;
763 
764  GetDIR(dir, dirp);
765  closedir(dirp->dir);
766  dirp->dir = NULL;
767 
768  return Qnil;
769 }
770 
771 static void
773 {
774  if (chdir(RSTRING_PTR(path)) < 0)
776 }
777 
778 static int chdir_blocking = 0;
780 
781 struct chdir_data {
783  int done;
784 };
785 
786 static VALUE
787 chdir_yield(struct chdir_data *args)
788 {
789  dir_chdir(args->new_path);
790  args->done = TRUE;
791  chdir_blocking++;
792  if (chdir_thread == Qnil)
794  return rb_yield(args->new_path);
795 }
796 
797 static VALUE
799 {
800  if (args->done) {
801  chdir_blocking--;
802  if (chdir_blocking == 0)
803  chdir_thread = Qnil;
804  dir_chdir(args->old_path);
805  }
806  return Qnil;
807 }
808 
809 /*
810  * call-seq:
811  * Dir.chdir( [ string] ) -> 0
812  * Dir.chdir( [ string] ) {| path | block } -> anObject
813  *
814  * Changes the current working directory of the process to the given
815  * string. When called without an argument, changes the directory to
816  * the value of the environment variable <code>HOME</code>, or
817  * <code>LOGDIR</code>. <code>SystemCallError</code> (probably
818  * <code>Errno::ENOENT</code>) if the target directory does not exist.
819  *
820  * If a block is given, it is passed the name of the new current
821  * directory, and the block is executed with that as the current
822  * directory. The original working directory is restored when the block
823  * exits. The return value of <code>chdir</code> is the value of the
824  * block. <code>chdir</code> blocks can be nested, but in a
825  * multi-threaded program an error will be raised if a thread attempts
826  * to open a <code>chdir</code> block while another thread has one
827  * open.
828  *
829  * Dir.chdir("/var/spool/mail")
830  * puts Dir.pwd
831  * Dir.chdir("/tmp") do
832  * puts Dir.pwd
833  * Dir.chdir("/usr") do
834  * puts Dir.pwd
835  * end
836  * puts Dir.pwd
837  * end
838  * puts Dir.pwd
839  *
840  * <em>produces:</em>
841  *
842  * /var/spool/mail
843  * /tmp
844  * /usr
845  * /tmp
846  * /var/spool/mail
847  */
848 static VALUE
850 {
851  VALUE path = Qnil;
852 
853  rb_secure(2);
854  if (rb_scan_args(argc, argv, "01", &path) == 1) {
855  FilePathValue(path);
856  path = rb_str_encode_ospath(path);
857  }
858  else {
859  const char *dist = getenv("HOME");
860  if (!dist) {
861  dist = getenv("LOGDIR");
862  if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
863  }
864  path = rb_str_new2(dist);
865  }
866 
867  if (chdir_blocking > 0) {
869  rb_warn("conflicting chdir during another chdir block");
870  }
871 
872  if (rb_block_given_p()) {
873  struct chdir_data args;
874 
876  args.new_path = path;
877  args.done = FALSE;
878  return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
879  }
880  dir_chdir(path);
881 
882  return INT2FIX(0);
883 }
884 
885 VALUE
887 {
888  char *path;
889  VALUE cwd;
890 
891  path = my_getcwd();
892  cwd = rb_tainted_str_new2(path);
894 
895  xfree(path);
896  return cwd;
897 }
898 
899 /*
900  * call-seq:
901  * Dir.getwd -> string
902  * Dir.pwd -> string
903  *
904  * Returns the path to the current working directory of this process as
905  * a string.
906  *
907  * Dir.chdir("/tmp") #=> 0
908  * Dir.getwd #=> "/tmp"
909  */
910 static VALUE
912 {
913  return rb_dir_getwd();
914 }
915 
916 static void
917 check_dirname(volatile VALUE *dir)
918 {
919  VALUE d = *dir;
920  char *path, *pend;
921  long len;
922  rb_encoding *enc;
923 
924  rb_secure(2);
925  FilePathValue(d);
926  enc = rb_enc_get(d);
927  RSTRING_GETMEM(d, path, len);
928  pend = path + len;
929  pend = rb_enc_path_end(rb_enc_path_skip_prefix(path, pend, enc), pend, enc);
930  if (pend - path < len) {
931  d = rb_str_subseq(d, 0, pend - path);
932  }
933  *dir = rb_str_encode_ospath(d);
934 }
935 
936 #if defined(HAVE_CHROOT)
937 /*
938  * call-seq:
939  * Dir.chroot( string ) -> 0
940  *
941  * Changes this process's idea of the file system root. Only a
942  * privileged process may make this call. Not available on all
943  * platforms. On Unix systems, see <code>chroot(2)</code> for more
944  * information.
945  */
946 static VALUE
947 dir_s_chroot(VALUE dir, VALUE path)
948 {
949  check_dirname(&path);
950  if (chroot(RSTRING_PTR(path)) == -1)
951  rb_sys_fail_path(path);
952 
953  return INT2FIX(0);
954 }
955 #else
956 #define dir_s_chroot rb_f_notimplement
957 #endif
958 
959 /*
960  * call-seq:
961  * Dir.mkdir( string [, integer] ) -> 0
962  *
963  * Makes a new directory named by <i>string</i>, with permissions
964  * specified by the optional parameter <i>anInteger</i>. The
965  * permissions may be modified by the value of
966  * <code>File::umask</code>, and are ignored on NT. Raises a
967  * <code>SystemCallError</code> if the directory cannot be created. See
968  * also the discussion of permissions in the class documentation for
969  * <code>File</code>.
970  *
971  * Dir.mkdir(File.join(Dir.home, ".foo"), 0700) #=> 0
972  *
973  */
974 static VALUE
976 {
977  VALUE path, vmode;
978  int mode;
979 
980  if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
981  mode = NUM2INT(vmode);
982  }
983  else {
984  mode = 0777;
985  }
986 
987  check_dirname(&path);
988  if (mkdir(RSTRING_PTR(path), mode) == -1)
989  rb_sys_fail_path(path);
990 
991  return INT2FIX(0);
992 }
993 
994 /*
995  * call-seq:
996  * Dir.delete( string ) -> 0
997  * Dir.rmdir( string ) -> 0
998  * Dir.unlink( string ) -> 0
999  *
1000  * Deletes the named directory. Raises a subclass of
1001  * <code>SystemCallError</code> if the directory isn't empty.
1002  */
1003 static VALUE
1005 {
1006  check_dirname(&dir);
1007  if (rmdir(RSTRING_PTR(dir)) < 0)
1008  rb_sys_fail_path(dir);
1009 
1010  return INT2FIX(0);
1011 }
1012 
1013 static VALUE
1015 {
1016  rb_sys_warning("%s:%s", strerror(errno), (const char *)mesg);
1017  return Qnil;
1018 }
1019 
1020 #define GLOB_VERBOSE (1U << (sizeof(int) * CHAR_BIT - 1))
1021 #define sys_warning(val) \
1022  (void)((flags & GLOB_VERBOSE) && rb_protect(sys_warning_1, (VALUE)(val), 0))
1023 
1024 #define GLOB_ALLOC(type) ((type *)malloc(sizeof(type)))
1025 #define GLOB_ALLOC_N(type, n) ((type *)malloc(sizeof(type) * (n)))
1026 #define GLOB_FREE(ptr) free(ptr)
1027 #define GLOB_JUMP_TAG(status) (((status) == -1) ? rb_memerror() : rb_jump_tag(status))
1028 
1029 /*
1030  * ENOTDIR can be returned by stat(2) if a non-leaf element of the path
1031  * is not a directory.
1032  */
1033 #define to_be_ignored(e) ((e) == ENOENT || (e) == ENOTDIR)
1034 
1035 #ifdef _WIN32
1036 #define STAT(p, s) rb_w32_ustati64((p), (s))
1037 #else
1038 #define STAT(p, s) stat((p), (s))
1039 #endif
1040 
1041 /* System call with warning */
1042 static int
1043 do_stat(const char *path, struct stat *pst, int flags)
1044 
1045 {
1046  int ret = STAT(path, pst);
1047  if (ret < 0 && !to_be_ignored(errno))
1048  sys_warning(path);
1049 
1050  return ret;
1051 }
1052 
1053 #if defined HAVE_LSTAT || defined lstat
1054 static int
1055 do_lstat(const char *path, struct stat *pst, int flags)
1056 {
1057  int ret = lstat(path, pst);
1058  if (ret < 0 && !to_be_ignored(errno))
1059  sys_warning(path);
1060 
1061  return ret;
1062 }
1063 #else
1064 #define do_lstat do_stat
1065 #endif
1066 
1067 static DIR *
1068 do_opendir(const char *path, int flags, rb_encoding *enc)
1069 {
1070  DIR *dirp;
1071 #ifdef _WIN32
1072  volatile VALUE tmp;
1073  if (enc != rb_usascii_encoding() &&
1074  enc != rb_ascii8bit_encoding() &&
1075  enc != rb_utf8_encoding()) {
1076  tmp = rb_enc_str_new(path, strlen(path), enc);
1077  tmp = rb_str_encode_ospath(tmp);
1078  path = RSTRING_PTR(tmp);
1079  }
1080 #endif
1081  dirp = opendir(path);
1082  if (dirp == NULL && !to_be_ignored(errno))
1083  sys_warning(path);
1084 
1085  return dirp;
1086 }
1087 
1088 /* Return nonzero if S has any special globbing chars in it. */
1089 static int
1090 has_magic(const char *p, const char *pend, int flags, rb_encoding *enc)
1091 {
1092  const int escape = !(flags & FNM_NOESCAPE);
1093  const int nocase = flags & FNM_CASEFOLD;
1094 
1095  register char c;
1096 
1097  while (p < pend && (c = *p++) != 0) {
1098  switch (c) {
1099  case '*':
1100  case '?':
1101  case '[':
1102  return 1;
1103 
1104  case '\\':
1105  if (escape && !(c = *p++))
1106  return 0;
1107  continue;
1108 
1109  default:
1110  if (!FNM_SYSCASE && ISALPHA(c) && nocase)
1111  return 1;
1112  }
1113 
1114  p = Next(p-1, pend, enc);
1115  }
1116 
1117  return 0;
1118 }
1119 
1120 /* Find separator in globbing pattern. */
1121 static char *
1122 find_dirsep(const char *p, const char *pend, int flags, rb_encoding *enc)
1123 {
1124  const int escape = !(flags & FNM_NOESCAPE);
1125 
1126  register char c;
1127  int open = 0;
1128 
1129  while ((c = *p++) != 0) {
1130  switch (c) {
1131  case '[':
1132  open = 1;
1133  continue;
1134  case ']':
1135  open = 0;
1136  continue;
1137 
1138  case '/':
1139  if (!open)
1140  return (char *)p-1;
1141  continue;
1142 
1143  case '\\':
1144  if (escape && !(c = *p++))
1145  return (char *)p-1;
1146  continue;
1147  }
1148 
1149  p = Next(p-1, pend, enc);
1150  }
1151 
1152  return (char *)p-1;
1153 }
1154 
1155 /* Remove escaping backslashes */
1156 static char *
1157 remove_backslashes(char *p, register const char *pend, rb_encoding *enc)
1158 {
1159  char *t = p;
1160  char *s = p;
1161 
1162  while (*p) {
1163  if (*p == '\\') {
1164  if (t != s)
1165  memmove(t, s, p - s);
1166  t += p - s;
1167  s = ++p;
1168  if (!*p) break;
1169  }
1170  Inc(p, pend, enc);
1171  }
1172 
1173  while (*p++);
1174 
1175  if (t != s)
1176  memmove(t, s, p - s); /* move '\0' too */
1177 
1178  return p;
1179 }
1180 
1181 /* Globing pattern */
1183 
1185  char *str;
1188 };
1189 
1190 static void glob_free_pattern(struct glob_pattern *list);
1191 
1192 static struct glob_pattern *
1193 glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
1194 {
1195  struct glob_pattern *list, *tmp, **tail = &list;
1196  int dirsep = 0; /* pattern is terminated with '/' */
1197  int recursive = 0;
1198 
1199  while (p < e && *p) {
1200  tmp = GLOB_ALLOC(struct glob_pattern);
1201  if (!tmp) goto error;
1202  if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
1203  /* fold continuous RECURSIVEs (needed in glob_helper) */
1204  do { p += 3; while (*p == '/') p++; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
1205  tmp->type = RECURSIVE;
1206  tmp->str = 0;
1207  dirsep = 1;
1208  recursive = 1;
1209  }
1210  else {
1211  const char *m = find_dirsep(p, e, flags, enc);
1212  int magic = has_magic(p, m, flags, enc);
1213  char *buf;
1214 
1215  if (!magic && !recursive && *m) {
1216  const char *m2;
1217  while (!has_magic(m+1, m2 = find_dirsep(m+1, e, flags, enc), flags, enc) &&
1218  *m2) {
1219  m = m2;
1220  }
1221  }
1222  buf = GLOB_ALLOC_N(char, m-p+1);
1223  if (!buf) {
1224  GLOB_FREE(tmp);
1225  goto error;
1226  }
1227  memcpy(buf, p, m-p);
1228  buf[m-p] = '\0';
1229  tmp->type = magic ? MAGICAL : PLAIN;
1230  tmp->str = buf;
1231  if (*m) {
1232  dirsep = 1;
1233  p = m + 1;
1234  }
1235  else {
1236  dirsep = 0;
1237  p = m;
1238  }
1239  }
1240  *tail = tmp;
1241  tail = &tmp->next;
1242  }
1243 
1244  tmp = GLOB_ALLOC(struct glob_pattern);
1245  if (!tmp) {
1246  error:
1247  *tail = 0;
1249  return 0;
1250  }
1251  tmp->type = dirsep ? MATCH_DIR : MATCH_ALL;
1252  tmp->str = 0;
1253  *tail = tmp;
1254  tmp->next = 0;
1255 
1256  return list;
1257 }
1258 
1259 static void
1261 {
1262  while (list) {
1263  struct glob_pattern *tmp = list;
1264  list = list->next;
1265  if (tmp->str)
1266  GLOB_FREE(tmp->str);
1267  GLOB_FREE(tmp);
1268  }
1269 }
1270 
1271 static char *
1272 join_path(const char *path, long len, int dirsep, const char *name, size_t namlen)
1273 {
1274  char *buf = GLOB_ALLOC_N(char, len+namlen+(dirsep?1:0)+1);
1275 
1276  if (!buf) return 0;
1277  memcpy(buf, path, len);
1278  if (dirsep) {
1279  buf[len++] = '/';
1280  }
1281  memcpy(buf+len, name, namlen);
1282  buf[len+namlen] = '\0';
1283  return buf;
1284 }
1285 
1286 enum answer {UNKNOWN = -1, NO, YES};
1287 
1288 #ifndef S_ISDIR
1289 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
1290 #endif
1291 
1292 #ifndef S_ISLNK
1293 # ifndef S_IFLNK
1294 # define S_ISLNK(m) (0)
1295 # else
1296 # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
1297 # endif
1298 #endif
1299 
1300 struct glob_args {
1301  void (*func)(const char *, VALUE, void *);
1302  const char *path;
1305 };
1306 
1307 static VALUE
1309 {
1310  struct glob_args *args = (struct glob_args *)val;
1311 
1312  (*args->func)(args->path, args->value, args->enc);
1313  return Qnil;
1314 }
1315 
1316 #define glob_call_func(func, path, arg, enc) (*(func))((path), (arg), (enc))
1317 
1318 static int
1320  const char *path,
1321  int dirsep, /* '/' should be placed before appending child entry's name to 'path'. */
1322  enum answer exist, /* Does 'path' indicate an existing entry? */
1323  enum answer isdir, /* Does 'path' indicate a directory or a symlink to a directory? */
1324  struct glob_pattern **beg,
1325  struct glob_pattern **end,
1326  int flags,
1328  VALUE arg,
1329  rb_encoding *enc)
1330 {
1331  struct stat st;
1332  int status = 0;
1333  struct glob_pattern **cur, **new_beg, **new_end;
1334  int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
1335  int escape = !(flags & FNM_NOESCAPE);
1336  long pathlen;
1337 
1338  for (cur = beg; cur < end; ++cur) {
1339  struct glob_pattern *p = *cur;
1340  if (p->type == RECURSIVE) {
1341  recursive = 1;
1342  p = p->next;
1343  }
1344  switch (p->type) {
1345  case PLAIN:
1346  plain = 1;
1347  break;
1348  case MAGICAL:
1349  magical = 1;
1350  break;
1351  case MATCH_ALL:
1352  match_all = 1;
1353  break;
1354  case MATCH_DIR:
1355  match_dir = 1;
1356  break;
1357  case RECURSIVE:
1358  rb_bug("continuous RECURSIVEs");
1359  }
1360  }
1361 
1362  pathlen = strlen(path);
1363  if (*path) {
1364  if (match_all && exist == UNKNOWN) {
1365  if (do_lstat(path, &st, flags) == 0) {
1366  exist = YES;
1367  isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
1368  }
1369  else {
1370  exist = NO;
1371  isdir = NO;
1372  }
1373  }
1374  if (match_dir && isdir == UNKNOWN) {
1375  if (do_stat(path, &st, flags) == 0) {
1376  exist = YES;
1377  isdir = S_ISDIR(st.st_mode) ? YES : NO;
1378  }
1379  else {
1380  exist = NO;
1381  isdir = NO;
1382  }
1383  }
1384  if (match_all && exist == YES) {
1385  status = glob_call_func(func, path, arg, enc);
1386  if (status) return status;
1387  }
1388  if (match_dir && isdir == YES) {
1389  char *tmp = join_path(path, pathlen, dirsep, "", 0);
1390  if (!tmp) return -1;
1391  status = glob_call_func(func, tmp, arg, enc);
1392  GLOB_FREE(tmp);
1393  if (status) return status;
1394  }
1395  }
1396 
1397  if (exist == NO || isdir == NO) return 0;
1398 
1399  if (magical || recursive) {
1400  struct dirent *dp;
1401  DIR *dirp;
1402  IF_HAVE_HFS(int hfs_p);
1403  dirp = do_opendir(*path ? path : ".", flags, enc);
1404  if (dirp == NULL) return 0;
1405  IF_HAVE_HFS(hfs_p = is_hfs(dirp));
1406 
1407  while ((dp = READDIR(dirp, enc)) != NULL) {
1408  char *buf;
1409  enum answer new_isdir = UNKNOWN;
1410  const char *name;
1411  size_t namlen;
1412  int dotfile = 0;
1413  IF_HAVE_HFS(VALUE utf8str = Qnil);
1414 
1415  if (recursive && dp->d_name[0] == '.') {
1416  ++dotfile;
1417  if (!dp->d_name[1]) {
1418  /* unless DOTMATCH, skip current directories not to recurse infinitely */
1419  if (!(flags & FNM_DOTMATCH)) continue;
1420  ++dotfile;
1421  }
1422  else if (dp->d_name[1] == '.' && !dp->d_name[2]) {
1423  /* always skip parent directories not to recurse infinitely */
1424  continue;
1425  }
1426  }
1427 
1428  name = dp->d_name;
1429  namlen = NAMLEN(dp);
1430 # if HAVE_HFS
1431  if (hfs_p && has_nonascii(name, namlen)) {
1432  if (!NIL_P(utf8str = rb_str_normalize_ospath(name, namlen))) {
1433  RSTRING_GETMEM(utf8str, name, namlen);
1434  }
1435  }
1436 # endif
1437  buf = join_path(path, pathlen, dirsep, name, namlen);
1438  IF_HAVE_HFS(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
1439  if (!buf) {
1440  status = -1;
1441  break;
1442  }
1443  name = buf + pathlen + (dirsep != 0);
1444  if (recursive && dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1)) {
1445  /* RECURSIVE never match dot files unless FNM_DOTMATCH is set */
1446 #ifndef _WIN32
1447  if (do_lstat(buf, &st, flags) == 0)
1448  new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
1449  else
1450  new_isdir = NO;
1451 #else
1452  new_isdir = dp->d_isdir ? (!dp->d_isrep ? YES : UNKNOWN) : NO;
1453 #endif
1454  }
1455 
1456  new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, (end - beg) * 2);
1457  if (!new_beg) {
1458  GLOB_FREE(buf);
1459  status = -1;
1460  break;
1461  }
1462 
1463  for (cur = beg; cur < end; ++cur) {
1464  struct glob_pattern *p = *cur;
1465  if (p->type == RECURSIVE) {
1466  if (new_isdir == YES) /* not symlink but real directory */
1467  *new_end++ = p; /* append recursive pattern */
1468  p = p->next; /* 0 times recursion */
1469  }
1470  if (p->type == PLAIN || p->type == MAGICAL) {
1471  if (fnmatch(p->str, enc, name, flags) == 0)
1472  *new_end++ = p->next;
1473  }
1474  }
1475 
1476  status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end,
1477  flags, func, arg, enc);
1478  GLOB_FREE(buf);
1479  GLOB_FREE(new_beg);
1480  if (status) break;
1481  }
1482 
1483  closedir(dirp);
1484  }
1485  else if (plain) {
1486  struct glob_pattern **copy_beg, **copy_end, **cur2;
1487 
1488  copy_beg = copy_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
1489  if (!copy_beg) return -1;
1490  for (cur = beg; cur < end; ++cur)
1491  *copy_end++ = (*cur)->type == PLAIN ? *cur : 0;
1492 
1493  for (cur = copy_beg; cur < copy_end; ++cur) {
1494  if (*cur) {
1495  char *buf;
1496  char *name;
1497  size_t len = strlen((*cur)->str) + 1;
1498  name = GLOB_ALLOC_N(char, len);
1499  if (!name) {
1500  status = -1;
1501  break;
1502  }
1503  memcpy(name, (*cur)->str, len);
1504  if (escape)
1505  len = remove_backslashes(name, name+len-1, enc) - name;
1506 
1507  new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
1508  if (!new_beg) {
1509  GLOB_FREE(name);
1510  status = -1;
1511  break;
1512  }
1513  *new_end++ = (*cur)->next;
1514  for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
1515  if (*cur2 && fnmatch((*cur2)->str, enc, name, flags) == 0) {
1516  *new_end++ = (*cur2)->next;
1517  *cur2 = 0;
1518  }
1519  }
1520 
1521  buf = join_path(path, pathlen, dirsep, name, len);
1522  GLOB_FREE(name);
1523  if (!buf) {
1524  GLOB_FREE(new_beg);
1525  status = -1;
1526  break;
1527  }
1528  status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg,
1529  new_end, flags, func, arg, enc);
1530  GLOB_FREE(buf);
1531  GLOB_FREE(new_beg);
1532  if (status) break;
1533  }
1534  }
1535 
1536  GLOB_FREE(copy_beg);
1537  }
1538 
1539  return status;
1540 }
1541 
1542 static int
1543 ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
1544 {
1545  struct glob_pattern *list;
1546  const char *root, *start;
1547  char *buf;
1548  size_t n;
1549  int status;
1550 
1551  start = root = path;
1552  flags |= FNM_SYSCASE;
1553 #if defined DOSISH
1554  root = rb_enc_path_skip_prefix(root, root + strlen(root), enc);
1555 #endif
1556 
1557  if (root && *root == '/') root++;
1558 
1559  n = root - start;
1560  buf = GLOB_ALLOC_N(char, n + 1);
1561  if (!buf) return -1;
1562  MEMCPY(buf, start, char, n);
1563  buf[n] = '\0';
1564 
1565  list = glob_make_pattern(root, root + strlen(root), flags, enc);
1566  if (!list) {
1567  GLOB_FREE(buf);
1568  return -1;
1569  }
1570  status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg, enc);
1572  GLOB_FREE(buf);
1573 
1574  return status;
1575 }
1576 
1577 int
1578 ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
1579 {
1580  return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg,
1582 }
1583 
1584 static int
1585 rb_glob_caller(const char *path, VALUE a, void *enc)
1586 {
1587  int status;
1588  struct glob_args *args = (struct glob_args *)a;
1589 
1590  args->path = path;
1591  rb_protect(glob_func_caller, a, &status);
1592  return status;
1593 }
1594 
1595 static int
1596 rb_glob2(const char *path, int flags,
1597  void (*func)(const char *, VALUE, void *), VALUE arg,
1598  rb_encoding* enc)
1599 {
1600  struct glob_args args;
1601 
1602  args.func = func;
1603  args.value = arg;
1604  args.enc = enc;
1605 
1606  if (flags & FNM_SYSCASE) {
1607  rb_warning("Dir.glob() ignores File::FNM_CASEFOLD");
1608  }
1609 
1610  return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args,
1611  enc);
1612 }
1613 
1614 void
1615 rb_glob(const char *path, void (*func)(const char *, VALUE, void *), VALUE arg)
1616 {
1617  int status = rb_glob2(path, 0, func, arg, rb_ascii8bit_encoding());
1618  if (status) GLOB_JUMP_TAG(status);
1619 }
1620 
1621 static void
1622 push_pattern(const char *path, VALUE ary, void *enc)
1623 {
1625 }
1626 
1627 static int
1628 ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
1629  rb_encoding *enc)
1630 {
1631  const int escape = !(flags & FNM_NOESCAPE);
1632  const char *p = str;
1633  const char *pend = p + strlen(p);
1634  const char *s = p;
1635  const char *lbrace = 0, *rbrace = 0;
1636  int nest = 0, status = 0;
1637 
1638  while (*p) {
1639  if (*p == '{' && nest++ == 0) {
1640  lbrace = p;
1641  }
1642  if (*p == '}' && --nest <= 0) {
1643  rbrace = p;
1644  break;
1645  }
1646  if (*p == '\\' && escape) {
1647  if (!*++p) break;
1648  }
1649  Inc(p, pend, enc);
1650  }
1651 
1652  if (lbrace && rbrace) {
1653  size_t len = strlen(s) + 1;
1654  char *buf = GLOB_ALLOC_N(char, len);
1655  long shift;
1656 
1657  if (!buf) return -1;
1658  memcpy(buf, s, lbrace-s);
1659  shift = (lbrace-s);
1660  p = lbrace;
1661  while (p < rbrace) {
1662  const char *t = ++p;
1663  nest = 0;
1664  while (p < rbrace && !(*p == ',' && nest == 0)) {
1665  if (*p == '{') nest++;
1666  if (*p == '}') nest--;
1667  if (*p == '\\' && escape) {
1668  if (++p == rbrace) break;
1669  }
1670  Inc(p, pend, enc);
1671  }
1672  memcpy(buf+shift, t, p-t);
1673  strlcpy(buf+shift+(p-t), rbrace+1, len-(shift+(p-t)));
1674  status = ruby_brace_expand(buf, flags, func, arg, enc);
1675  if (status) break;
1676  }
1677  GLOB_FREE(buf);
1678  }
1679  else if (!lbrace && !rbrace) {
1680  status = (*func)(s, arg, enc);
1681  }
1682 
1683  return status;
1684 }
1685 
1686 struct brace_args {
1689  int flags;
1690 };
1691 
1692 static int
1693 glob_brace(const char *path, VALUE val, void *enc)
1694 {
1695  struct brace_args *arg = (struct brace_args *)val;
1696 
1697  return ruby_glob0(path, arg->flags, arg->func, arg->value, enc);
1698 }
1699 
1700 static int
1701 ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg,
1702  rb_encoding* enc)
1703 {
1704  struct brace_args args;
1705 
1706  args.func = func;
1707  args.value = arg;
1708  args.flags = flags;
1709  return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args, enc);
1710 }
1711 
1712 int
1713 ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
1714 {
1715  return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg,
1717 }
1718 
1719 int
1721 {
1722  return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg, enc);
1723 }
1724 
1725 static int
1726 push_glob(VALUE ary, VALUE str, int flags)
1727 {
1728  struct glob_args args;
1729  rb_encoding *enc = rb_enc_get(str);
1730 
1732  args.func = push_pattern;
1733  args.value = ary;
1734  args.enc = enc;
1735 
1736  RB_GC_GUARD(str);
1737  return ruby_brace_glob0(RSTRING_PTR(str), flags | GLOB_VERBOSE,
1738  rb_glob_caller, (VALUE)&args, enc);
1739 }
1740 
1741 static VALUE
1742 rb_push_glob(VALUE str, int flags) /* '\0' is delimiter */
1743 {
1744  long offset = 0;
1745  VALUE ary;
1746 
1747  GlobPathValue(str, TRUE);
1748  ary = rb_ary_new();
1749 
1750  while (offset < RSTRING_LEN(str)) {
1751  char *p, *pend;
1752  int status;
1753  p = RSTRING_PTR(str) + offset;
1754  status = push_glob(ary, rb_enc_str_new(p, strlen(p), rb_enc_get(str)),
1755  flags);
1756  if (status) GLOB_JUMP_TAG(status);
1757  if (offset >= RSTRING_LEN(str)) break;
1758  p += strlen(p) + 1;
1759  pend = RSTRING_PTR(str) + RSTRING_LEN(str);
1760  while (p < pend && !*p)
1761  p++;
1762  offset = p - RSTRING_PTR(str);
1763  }
1764 
1765  return ary;
1766 }
1767 
1768 static VALUE
1769 dir_globs(long argc, const VALUE *argv, int flags)
1770 {
1771  VALUE ary = rb_ary_new();
1772  long i;
1773 
1774  for (i = 0; i < argc; ++i) {
1775  int status;
1776  VALUE str = argv[i];
1777  GlobPathValue(str, TRUE);
1778  status = push_glob(ary, str, flags);
1779  if (status) GLOB_JUMP_TAG(status);
1780  }
1781 
1782  return ary;
1783 }
1784 
1785 /*
1786  * call-seq:
1787  * Dir[ string [, string ...] ] -> array
1788  *
1789  * Equivalent to calling
1790  * <code>Dir.glob([</code><i>string,...</i><code>],0)</code>.
1791  *
1792  */
1793 static VALUE
1795 {
1796  if (argc == 1) {
1797  return rb_push_glob(argv[0], 0);
1798  }
1799  return dir_globs(argc, argv, 0);
1800 }
1801 
1802 /*
1803  * call-seq:
1804  * Dir.glob( pattern, [flags] ) -> matches
1805  * Dir.glob( pattern, [flags] ) { |filename| block } -> nil
1806  *
1807  * Expands +pattern+, which is an Array of patterns or a pattern String, and
1808  * returns the results as +matches+ or as arguments given to the block.
1809  *
1810  * Note that this pattern is not a regexp, it's closer to a shell glob. See
1811  * File::fnmatch for the meaning of the +flags+ parameter. Note that case
1812  * sensitivity depends on your system (so File::FNM_CASEFOLD is ignored), as
1813  * does the order in which the results are returned.
1814  *
1815  * <code>*</code>::
1816  * Matches any file. Can be restricted by other values in the glob.
1817  * Equivalent to <code>/ .* /x</code> in regexp.
1818  *
1819  * <code>*</code>:: Matches all files
1820  * <code>c*</code>:: Matches all files beginning with <code>c</code>
1821  * <code>*c</code>:: Matches all files ending with <code>c</code>
1822  * <code>\*c\*</code>:: Match all files that have <code>c</code> in them
1823  * (including at the beginning or end).
1824  *
1825  * Note, this will not match Unix-like hidden files (dotfiles). In order
1826  * to include those in the match results, you must use the
1827  * File::FNM_DOTMATCH flag or something like <code>"{*,.*}"</code>.
1828  *
1829  * <code>**</code>::
1830  * Matches directories recursively.
1831  *
1832  * <code>?</code>::
1833  * Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
1834  *
1835  * <code>[set]</code>::
1836  * Matches any one character in +set+. Behaves exactly like character sets
1837  * in Regexp, including set negation (<code>[^a-z]</code>).
1838  *
1839  * <code>{p,q}</code>::
1840  * Matches either literal <code>p</code> or literal <code>q</code>.
1841  * Equivalent to pattern alternation in regexp.
1842  *
1843  * Matching literals may be more than one character in length. More than
1844  * two literals may be specified.
1845  *
1846  * <code> \\ </code>::
1847  * Escapes the next metacharacter.
1848  *
1849  * Note that this means you cannot use backslash on windows as part of a
1850  * glob, i.e. <code>Dir["c:\\foo*"]</code> will not work, use
1851  * <code>Dir["c:/foo*"]</code> instead.
1852  *
1853  * Examples:
1854  *
1855  * Dir["config.?"] #=> ["config.h"]
1856  * Dir.glob("config.?") #=> ["config.h"]
1857  * Dir.glob("*.[a-z][a-z]") #=> ["main.rb"]
1858  * Dir.glob("*.[^r]*") #=> ["config.h"]
1859  * Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"]
1860  * Dir.glob("*") #=> ["config.h", "main.rb"]
1861  * Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "..", "config.h", "main.rb"]
1862  *
1863  * rbfiles = File.join("**", "*.rb")
1864  * Dir.glob(rbfiles) #=> ["main.rb",
1865  * # "lib/song.rb",
1866  * # "lib/song/karaoke.rb"]
1867  * libdirs = File.join("**", "lib")
1868  * Dir.glob(libdirs) #=> ["lib"]
1869  *
1870  * librbfiles = File.join("**", "lib", "**", "*.rb")
1871  * Dir.glob(librbfiles) #=> ["lib/song.rb",
1872  * # "lib/song/karaoke.rb"]
1873  *
1874  * librbfiles = File.join("**", "lib", "*.rb")
1875  * Dir.glob(librbfiles) #=> ["lib/song.rb"]
1876  */
1877 static VALUE
1879 {
1880  VALUE str, rflags, ary;
1881  int flags;
1882 
1883  if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
1884  flags = NUM2INT(rflags);
1885  else
1886  flags = 0;
1887 
1888  ary = rb_check_array_type(str);
1889  if (NIL_P(ary)) {
1890  ary = rb_push_glob(str, flags);
1891  }
1892  else {
1893  volatile VALUE v = ary;
1894  ary = dir_globs(RARRAY_LEN(v), RARRAY_CONST_PTR(v), flags);
1895  }
1896 
1897  if (rb_block_given_p()) {
1898  rb_ary_each(ary);
1899  return Qnil;
1900  }
1901  return ary;
1902 }
1903 
1904 static VALUE
1906 {
1907  VALUE dir = rb_funcall2(rb_cDir, rb_intern("open"), argc, argv);
1908 
1910  return dir;
1911 }
1912 
1913 
1914 /*
1915  * call-seq:
1916  * Dir.foreach( dirname ) {| filename | block } -> nil
1917  * Dir.foreach( dirname, encoding: enc ) {| filename | block } -> nil
1918  * Dir.foreach( dirname ) -> an_enumerator
1919  * Dir.foreach( dirname, encoding: enc ) -> an_enumerator
1920  *
1921  * Calls the block once for each entry in the named directory, passing
1922  * the filename of each entry as a parameter to the block.
1923  *
1924  * If no block is given, an enumerator is returned instead.
1925  *
1926  * Dir.foreach("testdir") {|x| puts "Got #{x}" }
1927  *
1928  * <em>produces:</em>
1929  *
1930  * Got .
1931  * Got ..
1932  * Got config.h
1933  * Got main.rb
1934  *
1935  */
1936 static VALUE
1938 {
1939  VALUE dir;
1940 
1941  RETURN_ENUMERATOR(io, argc, argv);
1942  dir = dir_open_dir(argc, argv);
1943  rb_ensure(dir_each, dir, dir_close, dir);
1944  return Qnil;
1945 }
1946 
1947 /*
1948  * call-seq:
1949  * Dir.entries( dirname ) -> array
1950  * Dir.entries( dirname, encoding: enc ) -> array
1951  *
1952  * Returns an array containing all of the filenames in the given
1953  * directory. Will raise a <code>SystemCallError</code> if the named
1954  * directory doesn't exist.
1955  *
1956  * The optional <i>enc</i> argument specifies the encoding of the directory.
1957  * If not specified, the filesystem encoding is used.
1958  *
1959  * Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"]
1960  *
1961  */
1962 static VALUE
1964 {
1965  VALUE dir;
1966 
1967  dir = dir_open_dir(argc, argv);
1968  return rb_ensure(rb_Array, dir, dir_close, dir);
1969 }
1970 
1971 static int
1972 fnmatch_brace(const char *pattern, VALUE val, void *enc)
1973 {
1974  struct brace_args *arg = (struct brace_args *)val;
1975  VALUE path = arg->value;
1976  rb_encoding *enc_pattern = enc;
1977  rb_encoding *enc_path = rb_enc_get(path);
1978 
1979  if (enc_pattern != enc_path) {
1980  if (!rb_enc_asciicompat(enc_pattern))
1981  return FNM_NOMATCH;
1982  if (!rb_enc_asciicompat(enc_path))
1983  return FNM_NOMATCH;
1984  if (!rb_enc_str_asciionly_p(path)) {
1985  int cr = ENC_CODERANGE_7BIT;
1986  long len = strlen(pattern);
1987  if (rb_str_coderange_scan_restartable(pattern, pattern + len,
1988  enc_pattern, &cr) != len)
1989  return FNM_NOMATCH;
1990  if (cr != ENC_CODERANGE_7BIT)
1991  return FNM_NOMATCH;
1992  }
1993  }
1994  return (fnmatch(pattern, enc, RSTRING_PTR(path), arg->flags) == 0);
1995 }
1996 
1997 /*
1998  * call-seq:
1999  * File.fnmatch( pattern, path, [flags] ) -> (true or false)
2000  * File.fnmatch?( pattern, path, [flags] ) -> (true or false)
2001  *
2002  * Returns true if +path+ matches against +pattern+. The pattern is not a
2003  * regular expression; instead it follows rules similar to shell filename
2004  * globbing. It may contain the following metacharacters:
2005  *
2006  * <code>*</code>::
2007  * Matches any file. Can be restricted by other values in the glob.
2008  * Equivalent to <code>/ .* /x</code> in regexp.
2009  *
2010  * <code>*</code>:: Matches all files regular files
2011  * <code>c*</code>:: Matches all files beginning with <code>c</code>
2012  * <code>*c</code>:: Matches all files ending with <code>c</code>
2013  * <code>\*c*</code>:: Matches all files that have <code>c</code> in them
2014  * (including at the beginning or end).
2015  *
2016  * To match hidden files (that start with a <code>.</code> set the
2017  * File::FNM_DOTMATCH flag.
2018  *
2019  * <code>**</code>::
2020  * Matches directories recursively or files expansively.
2021  *
2022  * <code>?</code>::
2023  * Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
2024  *
2025  * <code>[set]</code>::
2026  * Matches any one character in +set+. Behaves exactly like character sets
2027  * in Regexp, including set negation (<code>[^a-z]</code>).
2028  *
2029  * <code> \ </code>::
2030  * Escapes the next metacharacter.
2031  *
2032  * <code>{a,b}</code>::
2033  * Matches pattern a and pattern b if File::FNM_EXTGLOB flag is enabled.
2034  * Behaves like a Regexp union (<code>(?:a|b)</code>).
2035  *
2036  * +flags+ is a bitwise OR of the <code>FNM_XXX</code> constants. The same
2037  * glob pattern and flags are used by Dir::glob.
2038  *
2039  * Examples:
2040  *
2041  * File.fnmatch('cat', 'cat') #=> true # match entire string
2042  * File.fnmatch('cat', 'category') #=> false # only match partial string
2043  *
2044  * File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default
2045  * File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB
2046  *
2047  * File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character
2048  * File.fnmatch('c??t', 'cat') #=> false # ditto
2049  * File.fnmatch('c*', 'cats') #=> true # '*' match 0 or more characters
2050  * File.fnmatch('c*t', 'c/a/b/t') #=> true # ditto
2051  * File.fnmatch('ca[a-z]', 'cat') #=> true # inclusive bracket expression
2052  * File.fnmatch('ca[^t]', 'cat') #=> false # exclusive bracket expression ('^' or '!')
2053  *
2054  * File.fnmatch('cat', 'CAT') #=> false # case sensitive
2055  * File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true # case insensitive
2056  *
2057  * File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false # wildcard doesn't match '/' on FNM_PATHNAME
2058  * File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false # ditto
2059  * File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false # ditto
2060  *
2061  * File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary
2062  * File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary
2063  * File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary
2064  * File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression
2065  *
2066  * File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading
2067  * File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true # period by default.
2068  * File.fnmatch('.*', '.profile') #=> true
2069  *
2070  * rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
2071  * File.fnmatch(rbfiles, 'main.rb') #=> false
2072  * File.fnmatch(rbfiles, './main.rb') #=> false
2073  * File.fnmatch(rbfiles, 'lib/song.rb') #=> true
2074  * File.fnmatch('**.rb', 'main.rb') #=> true
2075  * File.fnmatch('**.rb', './main.rb') #=> false
2076  * File.fnmatch('**.rb', 'lib/song.rb') #=> true
2077  * File.fnmatch('*', 'dave/.profile') #=> true
2078  *
2079  * pattern = '*' '/' '*'
2080  * File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME) #=> false
2081  * File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
2082  *
2083  * pattern = '**' '/' 'foo'
2084  * File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME) #=> true
2085  * File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME) #=> true
2086  * File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
2087  * File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
2088  * File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
2089  */
2090 static VALUE
2092 {
2093  VALUE pattern, path;
2094  VALUE rflags;
2095  int flags;
2096 
2097  if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
2098  flags = NUM2INT(rflags);
2099  else
2100  flags = 0;
2101 
2102  StringValue(pattern);
2103  FilePathStringValue(path);
2104 
2105  if (flags & FNM_EXTGLOB) {
2106  struct brace_args args;
2107 
2108  args.value = path;
2109  args.flags = flags;
2111  (VALUE)&args, rb_enc_get(pattern)) > 0)
2112  return Qtrue;
2113  }
2114  else {
2115  rb_encoding *enc = rb_enc_compatible(pattern, path);
2116  if (!enc) return Qfalse;
2117  if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
2118  return Qtrue;
2119  }
2120  RB_GC_GUARD(pattern);
2121 
2122  return Qfalse;
2123 }
2124 
2125 /*
2126  * call-seq:
2127  * Dir.home() -> "/home/me"
2128  * Dir.home("root") -> "/root"
2129  *
2130  * Returns the home directory of the current user or the named user
2131  * if given.
2132  */
2133 static VALUE
2135 {
2136  VALUE user;
2137  const char *u = 0;
2138 
2139  rb_check_arity(argc, 0, 1);
2140  user = (argc > 0) ? argv[0] : Qnil;
2141  if (!NIL_P(user)) {
2142  SafeStringValue(user);
2143  rb_must_asciicompat(user);
2144  u = StringValueCStr(user);
2145  if (*u) {
2146  return rb_home_dir_of(user, rb_str_new(0, 0));
2147  }
2148  }
2149  return rb_default_home_dir(rb_str_new(0, 0));
2150 
2151 }
2152 
2153 #if 0
2154 /*
2155  * call-seq:
2156  * Dir.exist?(file_name) -> true or false
2157  * Dir.exists?(file_name) -> true or false
2158  *
2159  * Returns <code>true</code> if the named file is a directory,
2160  * <code>false</code> otherwise.
2161  *
2162  */
2163 VALUE
2165 {
2166 }
2167 #endif
2168 
2169 static VALUE
2171 {
2172  rb_warning("Dir.exists? is a deprecated name, use Dir.exist? instead");
2173  return rb_file_directory_p(obj, fname);
2174 }
2175 
2176 /*
2177  * Objects of class <code>Dir</code> are directory streams representing
2178  * directories in the underlying file system. They provide a variety of
2179  * ways to list directories and their contents. See also
2180  * <code>File</code>.
2181  *
2182  * The directory used in these examples contains the two regular files
2183  * (<code>config.h</code> and <code>main.rb</code>), the parent
2184  * directory (<code>..</code>), and the directory itself
2185  * (<code>.</code>).
2186  */
2187 void
2189 {
2191 
2193 
2198 
2199  rb_define_method(rb_cDir,"initialize", dir_initialize, -1);
2200  rb_define_method(rb_cDir,"path", dir_path, 0);
2201  rb_define_method(rb_cDir,"to_path", dir_path, 0);
2202  rb_define_method(rb_cDir,"inspect", dir_inspect, 0);
2203  rb_define_method(rb_cDir,"read", dir_read, 0);
2204  rb_define_method(rb_cDir,"each", dir_each, 0);
2205  rb_define_method(rb_cDir,"rewind", dir_rewind, 0);
2206  rb_define_method(rb_cDir,"tell", dir_tell, 0);
2207  rb_define_method(rb_cDir,"seek", dir_seek, 1);
2208  rb_define_method(rb_cDir,"pos", dir_tell, 0);
2209  rb_define_method(rb_cDir,"pos=", dir_set_pos, 1);
2210  rb_define_method(rb_cDir,"close", dir_close, 0);
2211 
2221 
2226 
2229 
2230  /* Document-const: File::Constants::FNM_NOESCAPE
2231  *
2232  * Disables escapes in File.fnmatch and Dir.glob patterns
2233  */
2234  rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
2235 
2236  /* Document-const: File::Constants::FNM_PATHNAME
2237  *
2238  * Wildcards in File.fnmatch and Dir.glob patterns do not match directory
2239  * separators
2240  */
2241  rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
2242 
2243  /* Document-const: File::Constants::FNM_DOTMATCH
2244  *
2245  * The '*' wildcard matches filenames starting with "." in File.fnmatch
2246  * and Dir.glob patterns
2247  */
2248  rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
2249 
2250  /* Document-const: File::Constants::FNM_CASEFOLD
2251  *
2252  * Makes File.fnmatch patterns case insensitive (but not Dir.glob
2253  * patterns).
2254  */
2255  rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
2256 
2257  /* Document-const: File::Constants::FNM_EXTGLOB
2258  *
2259  * Allows file globbing through "{a,b}" in File.fnmatch patterns.
2260  */
2261  rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB));
2262  rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
2263 }
void rb_gc(void)
Definition: gc.c:5193
Definition: dir.c:1286
VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc)
Definition: string.c:695
static void dir_closed(void)
Definition: dir.c:501
static char * join_path(const char *path, long len, int dirsep, const char *name, size_t namlen)
Definition: dir.c:1272
#define dir_tell
Definition: dir.c:671
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:139
static void dir_free(void *ptr)
Definition: dir.c:366
static int chdir_blocking
Definition: dir.c:778
#define RARRAY_LEN(a)
Definition: ruby.h:878
void rb_bug(const char *fmt,...)
Definition: error.c:327
static VALUE dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:975
answer
Definition: dir.c:1286
static int ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1543
#define NAMLEN(dirent)
Definition: dir.c:33
#define FALSE
Definition: nkf.h:174
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1015
rb_encoding * enc
Definition: dir.c:1304
#define tail
Definition: st.c:108
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:340
static VALUE chdir_restore(struct chdir_data *args)
Definition: dir.c:798
size_t strlen(const char *)
#define Next(p, e, enc)
Definition: dir.c:127
static const rb_data_type_t dir_data_type
Definition: dir.c:381
static VALUE chdir_thread
Definition: dir.c:779
struct glob_pattern * next
Definition: dir.c:1187
#define NUM2INT(x)
Definition: ruby.h:630
#define FNM_EXTGLOB
Definition: dir.c:117
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1646
#define FilePathValue(v)
Definition: ruby.h:560
#define CLASS_OF(v)
Definition: ruby.h:440
enum glob_pattern_type type
Definition: dir.c:1186
void rb_file_const(const char *name, VALUE value)
Definition: file.c:5276
int ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1720
static VALUE dir_rewind(VALUE dir)
Definition: dir.c:740
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1909
static VALUE file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:2091
#define Qtrue
Definition: ruby.h:426
#define to_be_ignored(e)
Definition: dir.c:1033
int lstat(const char *path, struct stat *result)
void(* func)(const char *, VALUE, void *)
Definition: dir.c:1301
static VALUE dir_inspect(VALUE dir)
Definition: dir.c:526
static DIR * do_opendir(const char *path, int flags, rb_encoding *enc)
Definition: dir.c:1068
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1041
VALUE rb_ary_each(VALUE array)
Definition: array.c:1789
static void dir_chdir(VALUE path)
Definition: dir.c:772
static VALUE dir_s_alloc(VALUE klass)
Definition: dir.c:399
#define GLOB_FREE(ptr)
Definition: dir.c:1026
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:219
#define GLOB_ALLOC(type)
Definition: dir.c:1024
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *)
Definition: string.c:686
static int glob_brace(const char *path, VALUE val, void *enc)
Definition: dir.c:1693
static size_t dir_memsize(const void *ptr)
Definition: dir.c:376
void rb_must_asciicompat(VALUE)
Definition: string.c:1579
#define rb_check_arity
Definition: intern.h:296
#define dir_set_pos
Definition: dir.c:725
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:900
VALUE rb_cFile
Definition: file.c:140
#define dir_seek
Definition: dir.c:700
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
static VALUE glob_func_caller(VALUE val)
Definition: dir.c:1308
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
Definition: encoding.c:849
#define FilePathStringValue(v)
Definition: ruby.h:563
static char * bracket(const char *p, const char *pend, const char *s, const char *send, int flags, rb_encoding *enc)
Definition: dir.c:131
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:781
int ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
Definition: dir.c:1578
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:807
static VALUE dir_s_chdir(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:849
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:854
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:826
Definition: dir.c:1286
Definition: dir.h:19
void Init_Dir(void)
Definition: dir.c:2188
#define RB_GC_GUARD(v)
Definition: ruby.h:523
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:946
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:808
void rb_gc_mark(VALUE ptr)
Definition: gc.c:3607
static VALUE dir_globs(long argc, const VALUE *argv, int flags)
Definition: dir.c:1769
#define dirent
Definition: dir.c:32
rb_encoding * rb_utf8_encoding(void)
Definition: encoding.c:1257
VALUE rb_str_dup_frozen(VALUE)
int flags
Definition: dir.c:1689
static int ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1628
#define ENC_CODERANGE_7BIT
Definition: encoding.h:49
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
int rb_enc_toupper(int c, rb_encoding *enc)
Definition: encoding.c:1031
#define FNM_DOTMATCH
Definition: dir.c:115
void rewinddir(DIR *dirp)
#define ISALPHA(c)
Definition: ruby.h:1782
static VALUE dir_s_aref(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:1794
VALUE path
Definition: dir.c:354
#define UNESCAPE(p)
Definition: dir.c:204
VALUE value
Definition: dir.c:1688
char * rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc)
Definition: file.c:2861
static struct glob_pattern * glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
Definition: dir.c:1193
#define FNM_NOMATCH
Definition: dir.c:124
VALUE rb_Array(VALUE)
Definition: object.c:3038
int t(void)
Definition: conftest.c:13
VALUE rb_class_name(VALUE)
Definition: variable.c:391
int rb_block_given_p(void)
Definition: eval.c:712
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:232
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1561
VALUE rb_home_dir_of(VALUE user, VALUE result)
Definition: file.c:3002
#define dir_s_chroot
Definition: dir.c:956
#define GetDIR(obj, dirp)
Definition: dir.c:516
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2158
VALUE rb_ary_new(void)
Definition: array.c:499
static VALUE dir_s_home(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:2134
#define dp(v)
Definition: vm_debug.h:21
Definition: dir.c:1286
long telldir(DIR *dirp)
VALUE rb_thread_current(void)
Definition: thread.c:2405
#define NIL_P(v)
Definition: ruby.h:438
#define ISASCII(c)
Definition: ruby.h:1774
ruby_glob_func * func
Definition: dir.c:1687
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:611
Definition: dir.c:1182
VALUE new_path
Definition: dir.c:782
#define sys_warning(val)
Definition: dir.c:1021
#define ISEND(p)
Definition: dir.c:205
#define GLOB_VERBOSE
Definition: dir.c:1020
int argc
Definition: ruby.c:131
#define GLOB_JUMP_TAG(status)
Definition: dir.c:1027
#define Qfalse
Definition: ruby.h:425
DIR * dir
Definition: dir.c:353
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1360
#define rb_str_new2
Definition: intern.h:840
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:155
static void check_dirname(volatile VALUE *dir)
Definition: dir.c:917
const char * path
Definition: dir.c:1302
void seekdir(DIR *dirp, long offset)
static VALUE chdir_yield(struct chdir_data *args)
Definition: dir.c:787
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2024
#define RETURN(val)
Definition: dir.c:206
#define Inc(p, e, enc)
Definition: dir.c:128
#define FNM_SYSCASE
Definition: dir.c:121
#define FNM_CASEFOLD
Definition: dir.c:116
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:1838
#define RSTRING_LEN(str)
Definition: ruby.h:841
VALUE rb_yield(VALUE)
Definition: vm_eval.c:948
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:886
int errno
#define TRUE
Definition: nkf.h:175
VALUE rb_mEnumerable
Definition: enum.c:20
int done
Definition: dir.c:783
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:958
static VALUE dir_read(VALUE dir)
Definition: dir.c:581
#define const
Definition: strftime.c:102
static int rb_glob_caller(const char *path, VALUE a, void *enc)
Definition: dir.c:1585
static int fnmatch_helper(const char **pcur, const char **scur, int flags, rb_encoding *enc)
Definition: dir.c:209
static VALUE sys_warning_1(VALUE mesg)
Definition: dir.c:1014
int ruby_glob_func(const char *, VALUE, void *)
Definition: ruby.h:1366
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1719
static void dir_mark(void *ptr)
Definition: dir.c:359
#define S_ISDIR(m)
Definition: dir.c:1289
static VALUE dir_s_rmdir(VALUE obj, VALUE dir)
Definition: dir.c:1004
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
unsigned long ID
Definition: ruby.h:89
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1272
VALUE rb_cDir
Definition: dir.c:350
VALUE rb_file_directory_p(VALUE obj, VALUE fname)
Definition: file.c:1216
#define Qnil
Definition: ruby.h:427
static int glob_helper(const char *path, int dirsep, enum answer exist, enum answer isdir, struct glob_pattern **beg, struct glob_pattern **end, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1319
#define glob_call_func(func, path, arg, enc)
Definition: dir.c:1316
#define READDIR(dir, enc)
Definition: dir.c:565
unsigned long VALUE
Definition: ruby.h:88
#define rb_funcall2
Definition: ruby.h:1464
static VALUE dir_each(VALUE dir)
Definition: dir.c:618
char * strchr(char *, char)
static VALUE dir_path(VALUE dir)
Definition: dir.c:553
char * str
Definition: dir.c:1185
char * getenv()
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
Definition: strlcpy.c:44
static VALUE rb_dir_exists_p(VALUE obj, VALUE fname)
Definition: dir.c:2170
#define rb_enc_asciicompat(enc)
Definition: encoding.h:188
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:839
VALUE rb_str_new_cstr(const char *)
Definition: string.c:560
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
static struct dir_data * dir_check(VALUE dir)
Definition: dir.c:507
#define FNM_PATHNAME
Definition: dir.c:114
#define rb_tainted_str_new2
Definition: intern.h:844
static void shift(struct cparse_params *v, long act, VALUE tok, VALUE val)
Definition: cparse.c:662
void rb_sys_fail(const char *mesg)
Definition: error.c:1976
static int do_stat(const char *path, struct stat *pst, int flags)
Definition: dir.c:1043
void rb_glob(const char *path, void(*func)(const char *, VALUE, void *), VALUE arg)
Definition: dir.c:1615
VALUE rb_str_dup(VALUE)
Definition: string.c:1062
static VALUE dir_s_glob(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:1878
static VALUE dir_s_getwd(VALUE dir)
Definition: dir.c:911
#define my_getcwd()
Definition: util.h:70
#define StringValueCStr(v)
Definition: ruby.h:541
static int rb_glob2(const char *path, int flags, void(*func)(const char *, VALUE, void *), VALUE arg, rb_encoding *enc)
Definition: dir.c:1596
#define RSTRING_PTR(str)
Definition: ruby.h:845
static char * remove_backslashes(char *p, register const char *pend, rb_encoding *enc)
Definition: dir.c:1157
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:832
#define STAT(p, s)
Definition: dir.c:1038
#define INT2FIX(i)
Definition: ruby.h:231
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:520
static VALUE dir_close(VALUE)
Definition: dir.c:760
static VALUE dir_entries(int argc, VALUE *argv, VALUE io)
Definition: dir.c:1963
static void glob_free_pattern(struct glob_pattern *list)
Definition: dir.c:1260
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:632
static VALUE dir_initialize(int argc, VALUE *argv, VALUE dir)
Definition: dir.c:422
rb_encoding * enc
Definition: dir.c:355
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
#define opendir(s)
Definition: dir.h:38
#define IF_HAVE_HFS(something)
Definition: dir.c:110
VALUE rb_default_home_dir(VALUE result)
Definition: file.c:3019
struct rb_encoding_entry * list
Definition: encoding.c:47
rb_encoding * rb_filesystem_encoding(void)
Definition: encoding.c:1324
glob_pattern_type
Definition: dir.c:1182
static int push_glob(VALUE ary, VALUE str, int flags)
Definition: dir.c:1726
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1030
int ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
Definition: dir.c:1713
static void push_pattern(const char *path, VALUE ary, void *enc)
Definition: dir.c:1622
static int fnmatch(const char *pattern, rb_encoding *enc, const char *string, int flags)
Definition: dir.c:301
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:242
#define SafeStringValue(v)
Definition: ruby.h:545
static VALUE dir_open_dir(int argc, VALUE *argv)
Definition: dir.c:1905
char * rb_enc_path_end(const char *path, const char *end, rb_encoding *enc)
Definition: file.c:2929
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:548
#define rb_sys_fail_path(path)
Definition: internal.h:450
const char * name
Definition: nkf.c:208
static VALUE dir_s_open(int argc, VALUE *argv, VALUE klass)
Definition: dir.c:487
RUBY_EXTERN VALUE rb_eIOError
Definition: ruby.h:1611
static char * find_dirsep(const char *p, const char *pend, int flags, rb_encoding *enc)
Definition: dir.c:1122
VALUE old_path
Definition: dir.c:782
static VALUE dir_foreach(int argc, VALUE *argv, VALUE io)
Definition: dir.c:1937
VALUE rb_int2inum(SIGNED_VALUE n)
Definition: bignum.c:3192
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1242
void rb_warning(const char *fmt,...)
Definition: error.c:236
static VALUE rb_push_glob(VALUE str, int flags)
Definition: dir.c:1742
#define closedir(d)
Definition: dir.h:43
void rb_secure(int)
Definition: safe.c:88
#define rb_check_frozen(obj)
Definition: intern.h:277
static int fnmatch_brace(const char *pattern, VALUE val, void *enc)
Definition: dir.c:1972
Definition: dir.c:1182
Definition: dir.c:352
void void xfree(void *)
#define FNM_NOESCAPE
Definition: dir.c:113
#define rb_intern(str)
int rb_enc_str_asciionly_p(VALUE)
Definition: string.c:448
#define stat(path, st)
Definition: win32.h:213
#define do_lstat
Definition: dir.c:1064
#define NULL
Definition: _sdbm.c:102
#define Qundef
Definition: ruby.h:428
static int ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1701
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1479
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2297
void rb_warn(const char *fmt,...)
Definition: error.c:223
#define GLOB_ALLOC_N(type, n)
Definition: dir.c:1025
VALUE rb_eArgError
Definition: error.c:549
#define NUM2LONG(x)
Definition: ruby.h:600
VALUE value
Definition: dir.c:1303
VALUE rb_dir_getwd(void)
Definition: dir.c:886
#define GlobPathValue(str, safe)
Definition: dir.c:389
#define S_ISLNK(m)
Definition: dir.c:1294
char ** argv
Definition: ruby.c:132
void rb_sys_warning(const char *fmt,...)
Definition: error.c:2048
#define StringValue(v)
Definition: ruby.h:539
static int has_magic(const char *p, const char *pend, int flags, rb_encoding *enc)
Definition: dir.c:1090
VALUE rb_str_new(const char *, long)
Definition: string.c:534