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