Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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 *
131 bracket(
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
209 fnmatch_helper(
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 */
231 RETURN(FNM_NOMATCH);
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))
242 RETURN(FNM_NOMATCH);
243 ptmp = p;
244 stmp = s;
245 continue;
246
247 case '?':
248 if (ISEND(s))
249 RETURN(FNM_NOMATCH);
250 p++;
251 Inc(s, send, enc);
252 continue;
253
254 case '[': {
255 const char *t;
256 if (ISEND(s))
257 RETURN(FNM_NOMATCH);
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 }
296 RETURN(FNM_NOMATCH);
297 }
298 }
299
300 static int
301 fnmatch(
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
350 VALUE rb_cDir;
351
352 struct dir_data {
353 DIR *dir;
354 VALUE path;
355 rb_encoding *enc;
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
381 static const rb_data_type_t dir_data_type = {
382 "dir",
383 {dir_mark, dir_free, dir_memsize,},
384 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
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
399 dir_s_alloc(VALUE klass)
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
422 dir_initialize(int argc, VALUE *argv, VALUE dir)
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
450 TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dp);
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
487 dir_s_open(int argc, VALUE *argv, VALUE klass)
488 {
489 struct dir_data *dp;
490 VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);
491
492 dir_initialize(argc, argv, dir);
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
501 dir_closed(void)
502 {
503 rb_raise(rb_eIOError, "closed directory");
504 }
505
506 static struct dir_data *
507 dir_check(VALUE dir)
508 {
509 struct dir_data *dirp;
510 rb_check_frozen(dir);
511 dirp = rb_check_typeddata(dir, &dir_data_type);
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
526 dir_inspect(VALUE dir)
527 {
528 struct dir_data *dirp;
529
530 TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
531 if (!NIL_P(dirp->path)) {
532 VALUE str = rb_str_new_cstr("#<");
533 rb_str_append(str, rb_class_name(CLASS_OF(dir)));
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
553 dir_path(VALUE dir)
554 {
555 struct dir_data *dirp;
556
557 TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
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
581 dir_read(VALUE dir)
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
618 dir_each(VALUE dir)
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
719 dir_set_pos(VALUE dir, VALUE pos)
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
740 dir_rewind(VALUE dir)
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
760 dir_close(VALUE dir)
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
772 dir_chdir(VALUE path)
773 {
774 if (chdir(RSTRING_PTR(path)) < 0)
775 rb_sys_fail_path(path);
776 }
777
778 static int chdir_blocking = 0;
779 static VALUE chdir_thread = Qnil;
780
781 struct chdir_data {
782 VALUE old_path, new_path;
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)
793 chdir_thread = rb_thread_current();
794 return rb_yield(args->new_path);
795 }
796
797 static VALUE
798 chdir_restore(struct chdir_data *args)
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
849 dir_s_chdir(int argc, VALUE *argv, VALUE obj)
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) {
868 if (!rb_block_given_p() || rb_thread_current() != chdir_thread)
869 rb_warn("conflicting chdir during another chdir block");
870 }
871
872 if (rb_block_given_p()) {
873 struct chdir_data args;
874
875 args.old_path = rb_str_encode_ospath(rb_dir_getwd());
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
886 rb_dir_getwd(void)
887 {
888 char *path;
889 VALUE cwd;
890
891 path = my_getcwd();
892 cwd = rb_tainted_str_new2(path);
893 rb_enc_associate(cwd, rb_filesystem_encoding());
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
911 dir_s_getwd(VALUE dir)
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
975 dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
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
1004 dir_s_rmdir(VALUE obj, VALUE dir)
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
1014 sys_warning_1(VALUE mesg)
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 */
1182 enum glob_pattern_type { PLAIN, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
1183
1184 struct glob_pattern {
1185 char *str;
1186 enum glob_pattern_type type;
1187 struct glob_pattern *next;
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;
1248 glob_free_pattern(list);
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
1260 glob_free_pattern(struct glob_pattern *list)
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;
1303 VALUE value;
1304 rb_encoding *enc;
1305 };
1306
1307 static VALUE
1308 glob_func_caller(VALUE val)
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
1319 glob_helper(
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,
1327 ruby_glob_func *func,
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);
1571 glob_free_pattern(list);
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,
1581 rb_ascii8bit_encoding());
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 {
1624 rb_ary_push(ary, rb_external_str_new_with_enc(path, strlen(path), enc));
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 {
1687 ruby_glob_func *func;
1688 VALUE value;
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,
1716 rb_ascii8bit_encoding());
1717 }
1718
1719 int
1720 ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
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
1731 if (enc == rb_usascii_encoding()) enc = rb_filesystem_encoding();
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
1794 dir_s_aref(int argc, VALUE *argv, VALUE obj)
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
1878 dir_s_glob(int argc, VALUE *argv, VALUE obj)
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
1905 dir_open_dir(int argc, VALUE *argv)
1906 {
1907 VALUE dir = rb_funcall2(rb_cDir, rb_intern("open"), argc, argv);
1908
1909 rb_check_typeddata(dir, &dir_data_type);
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
1937 dir_foreach(int argc, VALUE *argv, VALUE io)
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
1963 dir_entries(int argc, VALUE *argv, VALUE io)
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
2091 file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
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;
2110 if (ruby_brace_expand(RSTRING_PTR(pattern), flags, fnmatch_brace,
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
2134 dir_s_home(int argc, VALUE *argv, VALUE obj)
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
2164 rb_file_directory_p()
2165 {
2166 }
2167 #endif
2168
2169 static VALUE
2170 rb_dir_exists_p(VALUE obj, VALUE fname)
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
2188 Init_Dir(void)
2189 {
2190 rb_cDir = rb_define_class("Dir", rb_cObject);
2191
2192 rb_include_module(rb_cDir, rb_mEnumerable);
2193
2194 rb_define_alloc_func(rb_cDir, dir_s_alloc);
2195 rb_define_singleton_method(rb_cDir, "open", dir_s_open, -1);
2196 rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, -1);
2197 rb_define_singleton_method(rb_cDir, "entries", dir_entries, -1);
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
2212 rb_define_singleton_method(rb_cDir,"chdir", dir_s_chdir, -1);
2213 rb_define_singleton_method(rb_cDir,"getwd", dir_s_getwd, 0);
2214 rb_define_singleton_method(rb_cDir,"pwd", dir_s_getwd, 0);
2215 rb_define_singleton_method(rb_cDir,"chroot", dir_s_chroot, 1);
2216 rb_define_singleton_method(rb_cDir,"mkdir", dir_s_mkdir, -1);
2217 rb_define_singleton_method(rb_cDir,"rmdir", dir_s_rmdir, 1);
2218 rb_define_singleton_method(rb_cDir,"delete", dir_s_rmdir, 1);
2219 rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
2220 rb_define_singleton_method(rb_cDir,"home", dir_s_home, -1);
2221
2222 rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
2223 rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, -1);
2224 rb_define_singleton_method(rb_cDir,"exist?", rb_file_directory_p, 1);
2225 rb_define_singleton_method(rb_cDir,"exists?", rb_dir_exists_p, 1);
2226
2227 rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
2228 rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
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 }
rb_gc
void rb_gc(void)
Definition: gc.c:5190
NO
Definition: dir.c:1286
rb_external_str_with_enc
VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc)
Definition: string.c:695
dir_closed
static void dir_closed(void)
Definition: dir.c:501
MATCH_DIR
Definition: dir.c:1182
join_path
static char * join_path(const char *path, long len, int dirsep, const char *name, size_t namlen)
Definition: dir.c:1272
dir_tell
#define dir_tell
Definition: dir.c:671
MBCLEN_CHARFOUND_P
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:139
dir_free
static void dir_free(void *ptr)
Definition: dir.c:366
chdir_blocking
static int chdir_blocking
Definition: dir.c:778
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:327
dir_s_mkdir
static VALUE dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:975
answer
answer
Definition: dir.c:1286
ruby_glob0
static int ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1543
NAMLEN
#define NAMLEN(dirent)
Definition: dir.c:33
FALSE
#define FALSE
Definition: nkf.h:174
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1015
glob_args::enc
rb_encoding * enc
Definition: dir.c:1304
tail
#define tail
Definition: st.c:108
rb_str_coderange_scan_restartable
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:340
chdir_restore
static VALUE chdir_restore(struct chdir_data *args)
Definition: dir.c:798
strlen
size_t strlen(const char *)
Next
#define Next(p, e, enc)
Definition: dir.c:127
dir_data_type
static const rb_data_type_t dir_data_type
Definition: dir.c:381
chdir_thread
static VALUE chdir_thread
Definition: dir.c:779
glob_pattern::next
struct glob_pattern * next
Definition: dir.c:1187
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:630
FNM_EXTGLOB
#define FNM_EXTGLOB
Definition: dir.c:117
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1655
ruby.h
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:560
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:440
glob_pattern::type
enum glob_pattern_type type
Definition: dir.c:1186
rb_file_const
void rb_file_const(const char *name, VALUE value)
Definition: file.c:5275
ruby_brace_glob_with_enc
int ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1720
dir_rewind
static VALUE dir_rewind(VALUE dir)
Definition: dir.c:740
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1918
file_s_fnmatch
static VALUE file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:2091
Qtrue
#define Qtrue
Definition: ruby.h:426
to_be_ignored
#define to_be_ignored(e)
Definition: dir.c:1033
lstat
int lstat(const char *path, struct stat *result)
dir_inspect
static VALUE dir_inspect(VALUE dir)
Definition: dir.c:526
do_opendir
static DIR * do_opendir(const char *path, int flags, rb_encoding *enc)
Definition: dir.c:1068
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1041
rb_ary_each
VALUE rb_ary_each(VALUE array)
Definition: array.c:1778
dir_chdir
static void dir_chdir(VALUE path)
Definition: dir.c:772
dir_s_alloc
static VALUE dir_s_alloc(VALUE klass)
Definition: dir.c:399
GLOB_FREE
#define GLOB_FREE(ptr)
Definition: dir.c:1026
rb_to_encoding
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:219
GLOB_ALLOC
#define GLOB_ALLOC(type)
Definition: dir.c:1024
rb_external_str_new_with_enc
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *)
Definition: string.c:686
glob_brace
static int glob_brace(const char *path, VALUE val, void *enc)
Definition: dir.c:1693
dir_memsize
static size_t dir_memsize(const void *ptr)
Definition: dir.c:376
rb_must_asciicompat
void rb_must_asciicompat(VALUE)
Definition: string.c:1580
rb_check_arity
#define rb_check_arity
Definition: intern.h:296
dir_set_pos
#define dir_set_pos
Definition: dir.c:725
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
rb_cFile
VALUE rb_cFile
Definition: file.c:139
dir_seek
#define dir_seek
Definition: dir.c:700
glob_func_caller
static VALUE glob_func_caller(VALUE val)
Definition: dir.c:1308
rb_enc_compatible
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
Definition: encoding.c:849
FilePathStringValue
#define FilePathStringValue(v)
Definition: ruby.h:563
bracket
static char * bracket(const char *p, const char *pend, const char *s, const char *send, int flags, rb_encoding *enc)
Definition: dir.c:131
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
ruby_glob
int ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
Definition: dir.c:1578
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:807
dir_s_chdir
static VALUE dir_s_chdir(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:849
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
RSTRING_GETMEM
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:854
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:826
YES
Definition: dir.c:1286
DIR
Definition: dir.h:19
Init_Dir
void Init_Dir(void)
Definition: dir.c:2188
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:523
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_enc_mbclen
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:946
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:827
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:3604
dir_globs
static VALUE dir_globs(long argc, const VALUE *argv, int flags)
Definition: dir.c:1769
dirent
#define dirent
Definition: dir.c:32
rb_utf8_encoding
rb_encoding * rb_utf8_encoding(void)
Definition: encoding.c:1242
rb_str_dup_frozen
VALUE rb_str_dup_frozen(VALUE)
brace_args::flags
int flags
Definition: dir.c:1689
ruby_brace_expand
static int ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1628
dirent.h
ENC_CODERANGE_7BIT
#define ENC_CODERANGE_7BIT
Definition: encoding.h:49
memmove
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
rb_enc_toupper
int rb_enc_toupper(int c, rb_encoding *enc)
Definition: encoding.c:1031
FNM_DOTMATCH
#define FNM_DOTMATCH
Definition: dir.c:115
rewinddir
void rewinddir(DIR *dirp)
stat.h
ISALPHA
#define ISALPHA(c)
Definition: ruby.h:1774
dir_s_aref
static VALUE dir_s_aref(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:1794
dir_data::path
VALUE path
Definition: dir.c:354
UNESCAPE
#define UNESCAPE(p)
Definition: dir.c:204
brace_args::value
VALUE value
Definition: dir.c:1688
rb_enc_path_skip_prefix
char * rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc)
Definition: file.c:2860
glob_make_pattern
static struct glob_pattern * glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
Definition: dir.c:1193
FNM_NOMATCH
#define FNM_NOMATCH
Definition: dir.c:124
rb_Array
VALUE rb_Array(VALUE)
Definition: object.c:3014
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:391
brace_args
Definition: dir.c:1686
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:712
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:231
val
#define val
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
rb_home_dir_of
VALUE rb_home_dir_of(VALUE user, VALUE result)
Definition: file.c:3001
dir_s_chroot
#define dir_s_chroot
Definition: dir.c:956
GetDIR
#define GetDIR(obj, dirp)
Definition: dir.c:516
rb_str_cat2
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2159
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:495
dir_s_home
static VALUE dir_s_home(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:2134
dp
#define dp(v)
Definition: vm_debug.h:21
glob_args
Definition: dir.c:1300
UNKNOWN
Definition: dir.c:1286
telldir
long telldir(DIR *dirp)
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2401
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
ISASCII
#define ISASCII(c)
Definition: ruby.h:1766
brace_args::func
ruby_glob_func * func
Definition: dir.c:1687
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:630
PLAIN
Definition: dir.c:1182
chdir_data::new_path
VALUE new_path
Definition: dir.c:782
unistd.h
sys_warning
#define sys_warning(val)
Definition: dir.c:1021
ISEND
#define ISEND(p)
Definition: dir.c:205
GLOB_VERBOSE
#define GLOB_VERBOSE
Definition: dir.c:1020
argc
int argc
Definition: ruby.c:131
GLOB_JUMP_TAG
#define GLOB_JUMP_TAG(status)
Definition: dir.c:1027
Qfalse
#define Qfalse
Definition: ruby.h:425
dir_data::dir
DIR * dir
Definition: dir.c:353
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1352
rb_str_new2
#define rb_str_new2
Definition: intern.h:840
rb_enc_codepoint
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:155
check_dirname
static void check_dirname(volatile VALUE *dir)
Definition: dir.c:917
glob_args::path
const char * path
Definition: dir.c:1302
seekdir
void seekdir(DIR *dirp, long offset)
chdir_yield
static VALUE chdir_yield(struct chdir_data *args)
Definition: dir.c:787
encoding.h
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2025
RETURN
#define RETURN(val)
Definition: dir.c:206
Inc
#define Inc(p, e, enc)
Definition: dir.c:128
FNM_SYSCASE
#define FNM_SYSCASE
Definition: dir.c:121
FNM_CASEFOLD
#define FNM_CASEFOLD
Definition: dir.c:116
rb_str_subseq
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:1839
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:942
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:886
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
errno
int errno
util.h
TRUE
#define TRUE
Definition: nkf.h:175
glob_args::func
void(* func)(const char *, VALUE, void *)
Definition: dir.c:1301
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
chdir_data::done
int done
Definition: dir.c:783
rb_enc_precise_mbclen
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:958
dir_read
static VALUE dir_read(VALUE dir)
Definition: dir.c:581
const
#define const
Definition: strftime.c:102
rb_glob_caller
static int rb_glob_caller(const char *path, VALUE a, void *enc)
Definition: dir.c:1585
fnmatch_helper
static int fnmatch_helper(const char **pcur, const char **scur, int flags, rb_encoding *enc)
Definition: dir.c:209
sys_warning_1
static VALUE sys_warning_1(VALUE mesg)
Definition: dir.c:1014
ruby_glob_func
int ruby_glob_func(const char *, VALUE, void *)
Definition: ruby.h:1358
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
dir_mark
static void dir_mark(void *ptr)
Definition: dir.c:359
S_ISDIR
#define S_ISDIR(m)
Definition: dir.c:1289
dir_s_rmdir
static VALUE dir_s_rmdir(VALUE obj, VALUE dir)
Definition: dir.c:1004
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
internal.h
ID
unsigned long ID
Definition: ruby.h:89
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1257
rb_cDir
VALUE rb_cDir
Definition: dir.c:350
rb_file_directory_p
VALUE rb_file_directory_p(VALUE obj, VALUE fname)
Definition: file.c:1215
Qnil
#define Qnil
Definition: ruby.h:427
glob_helper
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
glob_call_func
#define glob_call_func(func, path, arg, enc)
Definition: dir.c:1316
READDIR
#define READDIR(dir, enc)
Definition: dir.c:565
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_funcall2
#define rb_funcall2
Definition: ruby.h:1456
dir_each
static VALUE dir_each(VALUE dir)
Definition: dir.c:618
strchr
char * strchr(char *, char)
glob_pattern
Definition: dir.c:1184
dir_path
static VALUE dir_path(VALUE dir)
Definition: dir.c:553
glob_pattern::str
char * str
Definition: dir.c:1185
getenv
char * getenv()
strlcpy
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
Definition: strlcpy.c:44
rb_dir_exists_p
static VALUE rb_dir_exists_p(VALUE obj, VALUE fname)
Definition: dir.c:2170
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
Definition: encoding.h:188
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:839
rb_str_new_cstr
VALUE rb_str_new_cstr(const char *)
Definition: string.c:560
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
dir_check
static struct dir_data * dir_check(VALUE dir)
Definition: dir.c:507
FNM_PATHNAME
#define FNM_PATHNAME
Definition: dir.c:114
rb_tainted_str_new2
#define rb_tainted_str_new2
Definition: intern.h:844
shift
static void shift(struct cparse_params *v, long act, VALUE tok, VALUE val)
Definition: cparse.c:662
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1976
do_stat
static int do_stat(const char *path, struct stat *pst, int flags)
Definition: dir.c:1043
rb_glob
void rb_glob(const char *path, void(*func)(const char *, VALUE, void *), VALUE arg)
Definition: dir.c:1615
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1062
dir_s_glob
static VALUE dir_s_glob(int argc, VALUE *argv, VALUE obj)
Definition: dir.c:1878
dir_s_getwd
static VALUE dir_s_getwd(VALUE dir)
Definition: dir.c:911
my_getcwd
#define my_getcwd()
Definition: util.h:70
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:541
rb_glob2
static int rb_glob2(const char *path, int flags, void(*func)(const char *, VALUE, void *), VALUE arg, rb_encoding *enc)
Definition: dir.c:1596
chdir_data
Definition: dir.c:781
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
remove_backslashes
static char * remove_backslashes(char *p, register const char *pend, rb_encoding *enc)
Definition: dir.c:1157
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:832
STAT
#define STAT(p, s)
Definition: dir.c:1038
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
rb_check_typeddata
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:520
dir_close
static VALUE dir_close(VALUE)
Definition: dir.c:760
dir_entries
static VALUE dir_entries(int argc, VALUE *argv, VALUE io)
Definition: dir.c:1963
glob_free_pattern
static void glob_free_pattern(struct glob_pattern *list)
Definition: dir.c:1260
rb_data_type_struct
Definition: ruby.h:966
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:628
dir_initialize
static VALUE dir_initialize(int argc, VALUE *argv, VALUE dir)
Definition: dir.c:422
dir_data::enc
rb_encoding * enc
Definition: dir.c:355
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
opendir
#define opendir(s)
Definition: dir.h:38
MATCH_ALL
Definition: dir.c:1182
IF_HAVE_HFS
#define IF_HAVE_HFS(something)
Definition: dir.c:110
rb_default_home_dir
VALUE rb_default_home_dir(VALUE result)
Definition: file.c:3018
list
struct rb_encoding_entry * list
Definition: encoding.c:47
RECURSIVE
Definition: dir.c:1182
rb_filesystem_encoding
rb_encoding * rb_filesystem_encoding(void)
Definition: encoding.c:1309
glob_pattern_type
glob_pattern_type
Definition: dir.c:1182
push_glob
static int push_glob(VALUE ary, VALUE str, int flags)
Definition: dir.c:1726
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1030
ruby_brace_glob
int ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
Definition: dir.c:1713
push_pattern
static void push_pattern(const char *path, VALUE ary, void *enc)
Definition: dir.c:1622
fnmatch
static int fnmatch(const char *pattern, rb_encoding *enc, const char *string, int flags)
Definition: dir.c:301
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:242
SafeStringValue
#define SafeStringValue(v)
Definition: ruby.h:545
dir_open_dir
static VALUE dir_open_dir(int argc, VALUE *argv)
Definition: dir.c:1905
rb_enc_path_end
char * rb_enc_path_end(const char *path, const char *end, rb_encoding *enc)
Definition: file.c:2928
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:548
rb_sys_fail_path
#define rb_sys_fail_path(path)
Definition: internal.h:450
name
const char * name
Definition: nkf.c:208
dir_s_open
static VALUE dir_s_open(int argc, VALUE *argv, VALUE klass)
Definition: dir.c:487
rb_eIOError
RUBY_EXTERN VALUE rb_eIOError
Definition: ruby.h:1603
find_dirsep
static char * find_dirsep(const char *p, const char *pend, int flags, rb_encoding *enc)
Definition: dir.c:1122
chdir_data::old_path
VALUE old_path
Definition: dir.c:782
dir_foreach
static VALUE dir_foreach(int argc, VALUE *argv, VALUE io)
Definition: dir.c:1937
rb_int2inum
VALUE rb_int2inum(SIGNED_VALUE n)
Definition: bignum.c:3192
rb_ascii8bit_encoding
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1227
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:236
rb_push_glob
static VALUE rb_push_glob(VALUE str, int flags)
Definition: dir.c:1742
closedir
#define closedir(d)
Definition: dir.h:43
rb_secure
void rb_secure(int)
Definition: safe.c:88
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:277
fnmatch_brace
static int fnmatch_brace(const char *pattern, VALUE val, void *enc)
Definition: dir.c:1972
MAGICAL
Definition: dir.c:1182
dir_data
Definition: dir.c:352
xfree
void void xfree(void *)
FNM_NOESCAPE
#define FNM_NOESCAPE
Definition: dir.c:113
rb_intern
#define rb_intern(str)
rb_enc_str_asciionly_p
int rb_enc_str_asciionly_p(VALUE)
Definition: string.c:448
stat
#define stat(path, st)
Definition: win32.h:213
do_lstat
#define do_lstat
Definition: dir.c:1064
NULL
#define NULL
Definition: _sdbm.c:103
Qundef
#define Qundef
Definition: ruby.h:428
ruby_brace_glob0
static int ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
Definition: dir.c:1701
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2298
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:223
GLOB_ALLOC_N
#define GLOB_ALLOC_N(type, n)
Definition: dir.c:1025
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:600
glob_args::value
VALUE value
Definition: dir.c:1303
rb_dir_getwd
VALUE rb_dir_getwd(void)
Definition: dir.c:886
GlobPathValue
#define GlobPathValue(str, safe)
Definition: dir.c:389
S_ISLNK
#define S_ISLNK(m)
Definition: dir.c:1294
argv
char ** argv
Definition: ruby.c:132
rb_sys_warning
void rb_sys_warning(const char *fmt,...)
Definition: error.c:2048
StringValue
#define StringValue(v)
Definition: ruby.h:539
dir.h
has_magic
static int has_magic(const char *p, const char *pend, int flags, rb_encoding *enc)
Definition: dir.c:1090
OnigEncodingTypeST
Definition: oniguruma.h:158
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:534