pathname 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1679 @@
1
+ #include "ruby.h"
2
+ #include "ruby/encoding.h"
3
+
4
+ static VALUE rb_cPathname;
5
+ static ID id_ENOTDIR;
6
+ static ID id_at_path;
7
+ static ID id_atime;
8
+ static ID id_base;
9
+ static ID id_basename;
10
+ static ID id_binread;
11
+ static ID id_binwrite;
12
+ static ID id_birthtime;
13
+ static ID id_blockdev_p;
14
+ static ID id_chardev_p;
15
+ static ID id_chmod;
16
+ static ID id_chown;
17
+ static ID id_ctime;
18
+ static ID id_directory_p;
19
+ static ID id_dirname;
20
+ static ID id_empty_p;
21
+ static ID id_entries;
22
+ static ID id_executable_p;
23
+ static ID id_executable_real_p;
24
+ static ID id_exist_p;
25
+ static ID id_expand_path;
26
+ static ID id_extname;
27
+ static ID id_file_p;
28
+ static ID id_fnmatch;
29
+ static ID id_foreach;
30
+ static ID id_ftype;
31
+ static ID id_getwd;
32
+ static ID id_glob;
33
+ static ID id_grpowned_p;
34
+ static ID id_lchmod;
35
+ static ID id_lchown;
36
+ static ID id_link;
37
+ static ID id_lstat;
38
+ static ID id_mkdir;
39
+ static ID id_mtime;
40
+ static ID id_open;
41
+ static ID id_owned_p;
42
+ static ID id_pipe_p;
43
+ static ID id_read;
44
+ static ID id_readable_p;
45
+ static ID id_readable_real_p;
46
+ static ID id_readlines;
47
+ static ID id_readlink;
48
+ static ID id_realdirpath;
49
+ static ID id_realpath;
50
+ static ID id_rename;
51
+ static ID id_rmdir;
52
+ static ID id_setgid_p;
53
+ static ID id_setuid_p;
54
+ static ID id_size;
55
+ static ID id_size_p;
56
+ static ID id_socket_p;
57
+ static ID id_split;
58
+ static ID id_stat;
59
+ static ID id_sticky_p;
60
+ static ID id_sub;
61
+ static ID id_symlink;
62
+ static ID id_symlink_p;
63
+ static ID id_sysopen;
64
+ static ID id_to_path;
65
+ static ID id_truncate;
66
+ static ID id_unlink;
67
+ static ID id_utime;
68
+ static ID id_world_readable_p;
69
+ static ID id_world_writable_p;
70
+ static ID id_writable_p;
71
+ static ID id_writable_real_p;
72
+ static ID id_write;
73
+ static ID id_zero_p;
74
+
75
+ static VALUE
76
+ get_strpath(VALUE obj)
77
+ {
78
+ VALUE strpath;
79
+ strpath = rb_ivar_get(obj, id_at_path);
80
+ if (!RB_TYPE_P(strpath, T_STRING))
81
+ rb_raise(rb_eTypeError, "unexpected @path");
82
+ return strpath;
83
+ }
84
+
85
+ static void
86
+ set_strpath(VALUE obj, VALUE val)
87
+ {
88
+ rb_ivar_set(obj, id_at_path, val);
89
+ }
90
+
91
+ /*
92
+ * Create a Pathname object from the given String (or String-like object).
93
+ * If +path+ contains a NULL character (<tt>\0</tt>), an ArgumentError is raised.
94
+ */
95
+ static VALUE
96
+ path_initialize(VALUE self, VALUE arg)
97
+ {
98
+ VALUE str;
99
+ if (RB_TYPE_P(arg, T_STRING)) {
100
+ str = arg;
101
+ }
102
+ else {
103
+ str = rb_check_funcall(arg, id_to_path, 0, NULL);
104
+ if (str == Qundef)
105
+ str = arg;
106
+ StringValue(str);
107
+ }
108
+ if (memchr(RSTRING_PTR(str), '\0', RSTRING_LEN(str)))
109
+ rb_raise(rb_eArgError, "pathname contains null byte");
110
+ str = rb_obj_dup(str);
111
+
112
+ set_strpath(self, str);
113
+ return self;
114
+ }
115
+
116
+ /*
117
+ * call-seq:
118
+ * pathname.freeze -> obj
119
+ *
120
+ * Freezes this Pathname.
121
+ *
122
+ * See Object.freeze.
123
+ */
124
+ static VALUE
125
+ path_freeze(VALUE self)
126
+ {
127
+ rb_call_super(0, 0);
128
+ rb_str_freeze(get_strpath(self));
129
+ return self;
130
+ }
131
+
132
+ /*
133
+ * call-seq:
134
+ * pathname.taint -> obj
135
+ *
136
+ * Returns pathname. This method is deprecated and will be removed in Ruby 3.2.
137
+ */
138
+ static VALUE
139
+ path_taint(VALUE self)
140
+ {
141
+ rb_warn("Pathname#taint is deprecated and will be removed in Ruby 3.2.");
142
+ return self;
143
+ }
144
+
145
+ /*
146
+ * call-seq:
147
+ * pathname.untaint -> obj
148
+ *
149
+ * Returns pathname. This method is deprecated and will be removed in Ruby 3.2.
150
+ */
151
+ static VALUE
152
+ path_untaint(VALUE self)
153
+ {
154
+ rb_warn("Pathname#untaint is deprecated and will be removed in Ruby 3.2.");
155
+ return self;
156
+ }
157
+
158
+ /*
159
+ * Compare this pathname with +other+. The comparison is string-based.
160
+ * Be aware that two different paths (<tt>foo.txt</tt> and <tt>./foo.txt</tt>)
161
+ * can refer to the same file.
162
+ */
163
+ static VALUE
164
+ path_eq(VALUE self, VALUE other)
165
+ {
166
+ if (!rb_obj_is_kind_of(other, rb_cPathname))
167
+ return Qfalse;
168
+ return rb_str_equal(get_strpath(self), get_strpath(other));
169
+ }
170
+
171
+ /*
172
+ * Provides a case-sensitive comparison operator for pathnames.
173
+ *
174
+ * Pathname.new('/usr') <=> Pathname.new('/usr/bin')
175
+ * #=> -1
176
+ * Pathname.new('/usr/bin') <=> Pathname.new('/usr/bin')
177
+ * #=> 0
178
+ * Pathname.new('/usr/bin') <=> Pathname.new('/USR/BIN')
179
+ * #=> 1
180
+ *
181
+ * It will return +-1+, +0+ or +1+ depending on the value of the left argument
182
+ * relative to the right argument. Or it will return +nil+ if the arguments
183
+ * are not comparable.
184
+ */
185
+ static VALUE
186
+ path_cmp(VALUE self, VALUE other)
187
+ {
188
+ VALUE s1, s2;
189
+ char *p1, *p2;
190
+ char *e1, *e2;
191
+ if (!rb_obj_is_kind_of(other, rb_cPathname))
192
+ return Qnil;
193
+ s1 = get_strpath(self);
194
+ s2 = get_strpath(other);
195
+ p1 = RSTRING_PTR(s1);
196
+ p2 = RSTRING_PTR(s2);
197
+ e1 = p1 + RSTRING_LEN(s1);
198
+ e2 = p2 + RSTRING_LEN(s2);
199
+ while (p1 < e1 && p2 < e2) {
200
+ int c1, c2;
201
+ c1 = (unsigned char)*p1++;
202
+ c2 = (unsigned char)*p2++;
203
+ if (c1 == '/') c1 = '\0';
204
+ if (c2 == '/') c2 = '\0';
205
+ if (c1 != c2) {
206
+ if (c1 < c2)
207
+ return INT2FIX(-1);
208
+ else
209
+ return INT2FIX(1);
210
+ }
211
+ }
212
+ if (p1 < e1)
213
+ return INT2FIX(1);
214
+ if (p2 < e2)
215
+ return INT2FIX(-1);
216
+ return INT2FIX(0);
217
+ }
218
+
219
+ #ifndef ST2FIX
220
+ #define ST2FIX(h) LONG2FIX((long)(h))
221
+ #endif
222
+
223
+ /* :nodoc: */
224
+ static VALUE
225
+ path_hash(VALUE self)
226
+ {
227
+ return ST2FIX(rb_str_hash(get_strpath(self)));
228
+ }
229
+
230
+ /*
231
+ * call-seq:
232
+ * pathname.to_s -> string
233
+ * pathname.to_path -> string
234
+ *
235
+ * Return the path as a String.
236
+ *
237
+ * to_path is implemented so Pathname objects are usable with File.open, etc.
238
+ */
239
+ static VALUE
240
+ path_to_s(VALUE self)
241
+ {
242
+ return rb_obj_dup(get_strpath(self));
243
+ }
244
+
245
+ /* :nodoc: */
246
+ static VALUE
247
+ path_inspect(VALUE self)
248
+ {
249
+ const char *c = rb_obj_classname(self);
250
+ VALUE str = get_strpath(self);
251
+ return rb_sprintf("#<%s:%"PRIsVALUE">", c, str);
252
+ }
253
+
254
+ /*
255
+ * Return a pathname which is substituted by String#sub.
256
+ *
257
+ * path1 = Pathname.new('/usr/bin/perl')
258
+ * path1.sub('perl', 'ruby')
259
+ * #=> #<Pathname:/usr/bin/ruby>
260
+ */
261
+ static VALUE
262
+ path_sub(int argc, VALUE *argv, VALUE self)
263
+ {
264
+ VALUE str = get_strpath(self);
265
+
266
+ if (rb_block_given_p()) {
267
+ str = rb_block_call(str, id_sub, argc, argv, 0, 0);
268
+ }
269
+ else {
270
+ str = rb_funcallv(str, id_sub, argc, argv);
271
+ }
272
+ return rb_class_new_instance(1, &str, rb_obj_class(self));
273
+ }
274
+
275
+ /*
276
+ * Return a pathname with +repl+ added as a suffix to the basename.
277
+ *
278
+ * If self has no extension part, +repl+ is appended.
279
+ *
280
+ * Pathname.new('/usr/bin/shutdown').sub_ext('.rb')
281
+ * #=> #<Pathname:/usr/bin/shutdown.rb>
282
+ */
283
+ static VALUE
284
+ path_sub_ext(VALUE self, VALUE repl)
285
+ {
286
+ VALUE str = get_strpath(self);
287
+ VALUE str2;
288
+ long extlen;
289
+ const char *ext;
290
+ const char *p;
291
+
292
+ StringValue(repl);
293
+ p = RSTRING_PTR(str);
294
+ extlen = RSTRING_LEN(str);
295
+ ext = ruby_enc_find_extname(p, &extlen, rb_enc_get(str));
296
+ if (ext == NULL) {
297
+ ext = p + RSTRING_LEN(str);
298
+ }
299
+ else if (extlen <= 1) {
300
+ ext += extlen;
301
+ }
302
+ str2 = rb_str_subseq(str, 0, ext-p);
303
+ rb_str_append(str2, repl);
304
+ return rb_class_new_instance(1, &str2, rb_obj_class(self));
305
+ }
306
+
307
+ /* Facade for File */
308
+
309
+ /*
310
+ * Returns the real (absolute) pathname for +self+ in the actual
311
+ * filesystem.
312
+ *
313
+ * Does not contain symlinks or useless dots, +..+ and +.+.
314
+ *
315
+ * All components of the pathname must exist when this method is
316
+ * called.
317
+ *
318
+ */
319
+ static VALUE
320
+ path_realpath(int argc, VALUE *argv, VALUE self)
321
+ {
322
+ VALUE basedir, str;
323
+ rb_scan_args(argc, argv, "01", &basedir);
324
+ str = rb_funcall(rb_cFile, id_realpath, 2, get_strpath(self), basedir);
325
+ return rb_class_new_instance(1, &str, rb_obj_class(self));
326
+ }
327
+
328
+ /*
329
+ * Returns the real (absolute) pathname of +self+ in the actual filesystem.
330
+ *
331
+ * Does not contain symlinks or useless dots, +..+ and +.+.
332
+ *
333
+ * The last component of the real pathname can be nonexistent.
334
+ */
335
+ static VALUE
336
+ path_realdirpath(int argc, VALUE *argv, VALUE self)
337
+ {
338
+ VALUE basedir, str;
339
+ rb_scan_args(argc, argv, "01", &basedir);
340
+ str = rb_funcall(rb_cFile, id_realdirpath, 2, get_strpath(self), basedir);
341
+ return rb_class_new_instance(1, &str, rb_obj_class(self));
342
+ }
343
+
344
+ /*
345
+ * call-seq:
346
+ * pathname.each_line {|line| ... }
347
+ * pathname.each_line(sep=$/ [, open_args]) {|line| block } -> nil
348
+ * pathname.each_line(limit [, open_args]) {|line| block } -> nil
349
+ * pathname.each_line(sep, limit [, open_args]) {|line| block } -> nil
350
+ * pathname.each_line(...) -> an_enumerator
351
+ *
352
+ * Iterates over each line in the file and yields a String object for each.
353
+ */
354
+ static VALUE
355
+ path_each_line(int argc, VALUE *argv, VALUE self)
356
+ {
357
+ VALUE args[4];
358
+ int n;
359
+
360
+ args[0] = get_strpath(self);
361
+ n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
362
+ if (rb_block_given_p()) {
363
+ return rb_block_call(rb_cFile, id_foreach, 1+n, args, 0, 0);
364
+ }
365
+ else {
366
+ return rb_funcallv(rb_cFile, id_foreach, 1+n, args);
367
+ }
368
+ }
369
+
370
+ /*
371
+ * call-seq:
372
+ * pathname.read([length [, offset]]) -> string
373
+ * pathname.read([length [, offset]], open_args) -> string
374
+ *
375
+ * Returns all data from the file, or the first +N+ bytes if specified.
376
+ *
377
+ * See File.read.
378
+ *
379
+ */
380
+ static VALUE
381
+ path_read(int argc, VALUE *argv, VALUE self)
382
+ {
383
+ VALUE args[4];
384
+ int n;
385
+
386
+ args[0] = get_strpath(self);
387
+ n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
388
+ return rb_funcallv_kw(rb_cFile, id_read, 1+n, args, RB_PASS_CALLED_KEYWORDS);
389
+ }
390
+
391
+ /*
392
+ * call-seq:
393
+ * pathname.binread([length [, offset]]) -> string
394
+ *
395
+ * Returns all the bytes from the file, or the first +N+ if specified.
396
+ *
397
+ * See File.binread.
398
+ *
399
+ */
400
+ static VALUE
401
+ path_binread(int argc, VALUE *argv, VALUE self)
402
+ {
403
+ VALUE args[3];
404
+ int n;
405
+
406
+ args[0] = get_strpath(self);
407
+ n = rb_scan_args(argc, argv, "02", &args[1], &args[2]);
408
+ return rb_funcallv(rb_cFile, id_binread, 1+n, args);
409
+ }
410
+
411
+ /*
412
+ * call-seq:
413
+ * pathname.write(string, [offset] ) => fixnum
414
+ * pathname.write(string, [offset], open_args ) => fixnum
415
+ *
416
+ * Writes +contents+ to the file.
417
+ *
418
+ * See File.write.
419
+ *
420
+ */
421
+ static VALUE
422
+ path_write(int argc, VALUE *argv, VALUE self)
423
+ {
424
+ VALUE args[4];
425
+ int n;
426
+
427
+ args[0] = get_strpath(self);
428
+ n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
429
+ return rb_funcallv_kw(rb_cFile, id_write, 1+n, args, RB_PASS_CALLED_KEYWORDS);
430
+ }
431
+
432
+ /*
433
+ * call-seq:
434
+ * pathname.binwrite(string, [offset] ) => fixnum
435
+ * pathname.binwrite(string, [offset], open_args ) => fixnum
436
+ *
437
+ * Writes +contents+ to the file, opening it in binary mode.
438
+ *
439
+ * See File.binwrite.
440
+ *
441
+ */
442
+ static VALUE
443
+ path_binwrite(int argc, VALUE *argv, VALUE self)
444
+ {
445
+ VALUE args[4];
446
+ int n;
447
+
448
+ args[0] = get_strpath(self);
449
+ n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
450
+ return rb_funcallv_kw(rb_cFile, id_binwrite, 1+n, args, RB_PASS_CALLED_KEYWORDS);
451
+ }
452
+
453
+ /*
454
+ * call-seq:
455
+ * pathname.readlines(sep=$/ [, open_args]) -> array
456
+ * pathname.readlines(limit [, open_args]) -> array
457
+ * pathname.readlines(sep, limit [, open_args]) -> array
458
+ *
459
+ * Returns all the lines from the file.
460
+ *
461
+ * See File.readlines.
462
+ *
463
+ */
464
+ static VALUE
465
+ path_readlines(int argc, VALUE *argv, VALUE self)
466
+ {
467
+ VALUE args[4];
468
+ int n;
469
+
470
+ args[0] = get_strpath(self);
471
+ n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
472
+ return rb_funcallv_kw(rb_cFile, id_readlines, 1+n, args, RB_PASS_CALLED_KEYWORDS);
473
+ }
474
+
475
+ /*
476
+ * call-seq:
477
+ * pathname.sysopen([mode, [perm]]) -> fixnum
478
+ *
479
+ * See IO.sysopen.
480
+ *
481
+ */
482
+ static VALUE
483
+ path_sysopen(int argc, VALUE *argv, VALUE self)
484
+ {
485
+ VALUE args[3];
486
+ int n;
487
+
488
+ args[0] = get_strpath(self);
489
+ n = rb_scan_args(argc, argv, "02", &args[1], &args[2]);
490
+ return rb_funcallv(rb_cIO, id_sysopen, 1+n, args);
491
+ }
492
+
493
+ /*
494
+ * call-seq:
495
+ * pathname.atime -> time
496
+ *
497
+ * Returns the last access time for the file.
498
+ *
499
+ * See File.atime.
500
+ */
501
+ static VALUE
502
+ path_atime(VALUE self)
503
+ {
504
+ return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self));
505
+ }
506
+
507
+ #if defined(HAVE_RB_FILE_S_BIRTHTIME)
508
+ /*
509
+ * call-seq:
510
+ * pathname.birthtime -> time
511
+ *
512
+ * Returns the birth time for the file.
513
+ * If the platform doesn't have birthtime, raises NotImplementedError.
514
+ *
515
+ * See File.birthtime.
516
+ */
517
+ static VALUE
518
+ path_birthtime(VALUE self)
519
+ {
520
+ return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self));
521
+ }
522
+ #else
523
+ /* check at compilation time for `respond_to?` */
524
+ # define path_birthtime rb_f_notimplement
525
+ #endif
526
+
527
+ /*
528
+ * call-seq:
529
+ * pathname.ctime -> time
530
+ *
531
+ * Returns the last change time, using directory information, not the file itself.
532
+ *
533
+ * See File.ctime.
534
+ */
535
+ static VALUE
536
+ path_ctime(VALUE self)
537
+ {
538
+ return rb_funcall(rb_cFile, id_ctime, 1, get_strpath(self));
539
+ }
540
+
541
+ /*
542
+ * call-seq:
543
+ * pathname.mtime -> time
544
+ *
545
+ * Returns the last modified time of the file.
546
+ *
547
+ * See File.mtime.
548
+ */
549
+ static VALUE
550
+ path_mtime(VALUE self)
551
+ {
552
+ return rb_funcall(rb_cFile, id_mtime, 1, get_strpath(self));
553
+ }
554
+
555
+ /*
556
+ * call-seq:
557
+ * pathname.chmod(mode_int) -> integer
558
+ *
559
+ * Changes file permissions.
560
+ *
561
+ * See File.chmod.
562
+ */
563
+ static VALUE
564
+ path_chmod(VALUE self, VALUE mode)
565
+ {
566
+ return rb_funcall(rb_cFile, id_chmod, 2, mode, get_strpath(self));
567
+ }
568
+
569
+ /*
570
+ * call-seq:
571
+ * pathname.lchmod(mode_int) -> integer
572
+ *
573
+ * Same as Pathname.chmod, but does not follow symbolic links.
574
+ *
575
+ * See File.lchmod.
576
+ */
577
+ static VALUE
578
+ path_lchmod(VALUE self, VALUE mode)
579
+ {
580
+ return rb_funcall(rb_cFile, id_lchmod, 2, mode, get_strpath(self));
581
+ }
582
+
583
+ /*
584
+ * call-seq:
585
+ * pathname.chown(owner_int, group_int) -> integer
586
+ *
587
+ * Change owner and group of the file.
588
+ *
589
+ * See File.chown.
590
+ */
591
+ static VALUE
592
+ path_chown(VALUE self, VALUE owner, VALUE group)
593
+ {
594
+ return rb_funcall(rb_cFile, id_chown, 3, owner, group, get_strpath(self));
595
+ }
596
+
597
+ /*
598
+ * call-seq:
599
+ * pathname.lchown(owner_int, group_int) -> integer
600
+ *
601
+ * Same as Pathname.chown, but does not follow symbolic links.
602
+ *
603
+ * See File.lchown.
604
+ */
605
+ static VALUE
606
+ path_lchown(VALUE self, VALUE owner, VALUE group)
607
+ {
608
+ return rb_funcall(rb_cFile, id_lchown, 3, owner, group, get_strpath(self));
609
+ }
610
+
611
+ /*
612
+ * call-seq:
613
+ * pathname.fnmatch(pattern, [flags]) -> true or false
614
+ * pathname.fnmatch?(pattern, [flags]) -> true or false
615
+ *
616
+ * Return +true+ if the receiver matches the given pattern.
617
+ *
618
+ * See File.fnmatch.
619
+ */
620
+ static VALUE
621
+ path_fnmatch(int argc, VALUE *argv, VALUE self)
622
+ {
623
+ VALUE str = get_strpath(self);
624
+ VALUE pattern, flags;
625
+ if (rb_scan_args(argc, argv, "11", &pattern, &flags) == 1)
626
+ return rb_funcall(rb_cFile, id_fnmatch, 2, pattern, str);
627
+ else
628
+ return rb_funcall(rb_cFile, id_fnmatch, 3, pattern, str, flags);
629
+ }
630
+
631
+ /*
632
+ * call-seq:
633
+ * pathname.ftype -> string
634
+ *
635
+ * Returns "type" of file ("file", "directory", etc).
636
+ *
637
+ * See File.ftype.
638
+ */
639
+ static VALUE
640
+ path_ftype(VALUE self)
641
+ {
642
+ return rb_funcall(rb_cFile, id_ftype, 1, get_strpath(self));
643
+ }
644
+
645
+ /*
646
+ * call-seq:
647
+ * pathname.make_link(old)
648
+ *
649
+ * Creates a hard link at _pathname_.
650
+ *
651
+ * See File.link.
652
+ */
653
+ static VALUE
654
+ path_make_link(VALUE self, VALUE old)
655
+ {
656
+ return rb_funcall(rb_cFile, id_link, 2, old, get_strpath(self));
657
+ }
658
+
659
+ /*
660
+ * call-seq:
661
+ * pathname.open()
662
+ * pathname.open(mode="r" [, opt]) -> file
663
+ * pathname.open([mode [, perm]] [, opt]) -> file
664
+ * pathname.open(mode="r" [, opt]) {|file| block } -> obj
665
+ * pathname.open([mode [, perm]] [, opt]) {|file| block } -> obj
666
+ *
667
+ * Opens the file for reading or writing.
668
+ *
669
+ * See File.open.
670
+ */
671
+ static VALUE
672
+ path_open(int argc, VALUE *argv, VALUE self)
673
+ {
674
+ VALUE args[4];
675
+ int n;
676
+
677
+ args[0] = get_strpath(self);
678
+ n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
679
+ if (rb_block_given_p()) {
680
+ return rb_block_call_kw(rb_cFile, id_open, 1+n, args, 0, 0, RB_PASS_CALLED_KEYWORDS);
681
+ }
682
+ else {
683
+ return rb_funcallv_kw(rb_cFile, id_open, 1+n, args, RB_PASS_CALLED_KEYWORDS);
684
+ }
685
+ }
686
+
687
+ /*
688
+ * Read symbolic link.
689
+ *
690
+ * See File.readlink.
691
+ */
692
+ static VALUE
693
+ path_readlink(VALUE self)
694
+ {
695
+ VALUE str;
696
+ str = rb_funcall(rb_cFile, id_readlink, 1, get_strpath(self));
697
+ return rb_class_new_instance(1, &str, rb_obj_class(self));
698
+ }
699
+
700
+ /*
701
+ * Rename the file.
702
+ *
703
+ * See File.rename.
704
+ */
705
+ static VALUE
706
+ path_rename(VALUE self, VALUE to)
707
+ {
708
+ return rb_funcall(rb_cFile, id_rename, 2, get_strpath(self), to);
709
+ }
710
+
711
+ /*
712
+ * Returns a File::Stat object.
713
+ *
714
+ * See File.stat.
715
+ */
716
+ static VALUE
717
+ path_stat(VALUE self)
718
+ {
719
+ return rb_funcall(rb_cFile, id_stat, 1, get_strpath(self));
720
+ }
721
+
722
+ /*
723
+ * See File.lstat.
724
+ */
725
+ static VALUE
726
+ path_lstat(VALUE self)
727
+ {
728
+ return rb_funcall(rb_cFile, id_lstat, 1, get_strpath(self));
729
+ }
730
+
731
+ /*
732
+ * call-seq:
733
+ * pathname.make_symlink(old)
734
+ *
735
+ * Creates a symbolic link.
736
+ *
737
+ * See File.symlink.
738
+ */
739
+ static VALUE
740
+ path_make_symlink(VALUE self, VALUE old)
741
+ {
742
+ return rb_funcall(rb_cFile, id_symlink, 2, old, get_strpath(self));
743
+ }
744
+
745
+ /*
746
+ * Truncates the file to +length+ bytes.
747
+ *
748
+ * See File.truncate.
749
+ */
750
+ static VALUE
751
+ path_truncate(VALUE self, VALUE length)
752
+ {
753
+ return rb_funcall(rb_cFile, id_truncate, 2, get_strpath(self), length);
754
+ }
755
+
756
+ /*
757
+ * Update the access and modification times of the file.
758
+ *
759
+ * See File.utime.
760
+ */
761
+ static VALUE
762
+ path_utime(VALUE self, VALUE atime, VALUE mtime)
763
+ {
764
+ return rb_funcall(rb_cFile, id_utime, 3, atime, mtime, get_strpath(self));
765
+ }
766
+
767
+ /*
768
+ * Returns the last component of the path.
769
+ *
770
+ * See File.basename.
771
+ */
772
+ static VALUE
773
+ path_basename(int argc, VALUE *argv, VALUE self)
774
+ {
775
+ VALUE str = get_strpath(self);
776
+ VALUE fext;
777
+ if (rb_scan_args(argc, argv, "01", &fext) == 0)
778
+ str = rb_funcall(rb_cFile, id_basename, 1, str);
779
+ else
780
+ str = rb_funcall(rb_cFile, id_basename, 2, str, fext);
781
+ return rb_class_new_instance(1, &str, rb_obj_class(self));
782
+ }
783
+
784
+ /*
785
+ * Returns all but the last component of the path.
786
+ *
787
+ * See File.dirname.
788
+ */
789
+ static VALUE
790
+ path_dirname(VALUE self)
791
+ {
792
+ VALUE str = get_strpath(self);
793
+ str = rb_funcall(rb_cFile, id_dirname, 1, str);
794
+ return rb_class_new_instance(1, &str, rb_obj_class(self));
795
+ }
796
+
797
+ /*
798
+ * Returns the file's extension.
799
+ *
800
+ * See File.extname.
801
+ */
802
+ static VALUE
803
+ path_extname(VALUE self)
804
+ {
805
+ VALUE str = get_strpath(self);
806
+ return rb_funcall(rb_cFile, id_extname, 1, str);
807
+ }
808
+
809
+ /*
810
+ * Returns the absolute path for the file.
811
+ *
812
+ * See File.expand_path.
813
+ */
814
+ static VALUE
815
+ path_expand_path(int argc, VALUE *argv, VALUE self)
816
+ {
817
+ VALUE str = get_strpath(self);
818
+ VALUE dname;
819
+ if (rb_scan_args(argc, argv, "01", &dname) == 0)
820
+ str = rb_funcall(rb_cFile, id_expand_path, 1, str);
821
+ else
822
+ str = rb_funcall(rb_cFile, id_expand_path, 2, str, dname);
823
+ return rb_class_new_instance(1, &str, rb_obj_class(self));
824
+ }
825
+
826
+ /*
827
+ * Returns the #dirname and the #basename in an Array.
828
+ *
829
+ * See File.split.
830
+ */
831
+ static VALUE
832
+ path_split(VALUE self)
833
+ {
834
+ VALUE str = get_strpath(self);
835
+ VALUE ary, dirname, basename;
836
+ ary = rb_funcall(rb_cFile, id_split, 1, str);
837
+ ary = rb_check_array_type(ary);
838
+ dirname = rb_ary_entry(ary, 0);
839
+ basename = rb_ary_entry(ary, 1);
840
+ dirname = rb_class_new_instance(1, &dirname, rb_obj_class(self));
841
+ basename = rb_class_new_instance(1, &basename, rb_obj_class(self));
842
+ return rb_ary_new3(2, dirname, basename);
843
+ }
844
+
845
+ /*
846
+ * See FileTest.blockdev?.
847
+ */
848
+ static VALUE
849
+ path_blockdev_p(VALUE self)
850
+ {
851
+ return rb_funcall(rb_mFileTest, id_blockdev_p, 1, get_strpath(self));
852
+ }
853
+
854
+ /*
855
+ * See FileTest.chardev?.
856
+ */
857
+ static VALUE
858
+ path_chardev_p(VALUE self)
859
+ {
860
+ return rb_funcall(rb_mFileTest, id_chardev_p, 1, get_strpath(self));
861
+ }
862
+
863
+ /*
864
+ * See FileTest.executable?.
865
+ */
866
+ static VALUE
867
+ path_executable_p(VALUE self)
868
+ {
869
+ return rb_funcall(rb_mFileTest, id_executable_p, 1, get_strpath(self));
870
+ }
871
+
872
+ /*
873
+ * See FileTest.executable_real?.
874
+ */
875
+ static VALUE
876
+ path_executable_real_p(VALUE self)
877
+ {
878
+ return rb_funcall(rb_mFileTest, id_executable_real_p, 1, get_strpath(self));
879
+ }
880
+
881
+ /*
882
+ * See FileTest.exist?.
883
+ */
884
+ static VALUE
885
+ path_exist_p(VALUE self)
886
+ {
887
+ return rb_funcall(rb_mFileTest, id_exist_p, 1, get_strpath(self));
888
+ }
889
+
890
+ /*
891
+ * See FileTest.grpowned?.
892
+ */
893
+ static VALUE
894
+ path_grpowned_p(VALUE self)
895
+ {
896
+ return rb_funcall(rb_mFileTest, id_grpowned_p, 1, get_strpath(self));
897
+ }
898
+
899
+ /*
900
+ * See FileTest.directory?.
901
+ */
902
+ static VALUE
903
+ path_directory_p(VALUE self)
904
+ {
905
+ return rb_funcall(rb_mFileTest, id_directory_p, 1, get_strpath(self));
906
+ }
907
+
908
+ /*
909
+ * See FileTest.file?.
910
+ */
911
+ static VALUE
912
+ path_file_p(VALUE self)
913
+ {
914
+ return rb_funcall(rb_mFileTest, id_file_p, 1, get_strpath(self));
915
+ }
916
+
917
+ /*
918
+ * See FileTest.pipe?.
919
+ */
920
+ static VALUE
921
+ path_pipe_p(VALUE self)
922
+ {
923
+ return rb_funcall(rb_mFileTest, id_pipe_p, 1, get_strpath(self));
924
+ }
925
+
926
+ /*
927
+ * See FileTest.socket?.
928
+ */
929
+ static VALUE
930
+ path_socket_p(VALUE self)
931
+ {
932
+ return rb_funcall(rb_mFileTest, id_socket_p, 1, get_strpath(self));
933
+ }
934
+
935
+ /*
936
+ * See FileTest.owned?.
937
+ */
938
+ static VALUE
939
+ path_owned_p(VALUE self)
940
+ {
941
+ return rb_funcall(rb_mFileTest, id_owned_p, 1, get_strpath(self));
942
+ }
943
+
944
+ /*
945
+ * See FileTest.readable?.
946
+ */
947
+ static VALUE
948
+ path_readable_p(VALUE self)
949
+ {
950
+ return rb_funcall(rb_mFileTest, id_readable_p, 1, get_strpath(self));
951
+ }
952
+
953
+ /*
954
+ * See FileTest.world_readable?.
955
+ */
956
+ static VALUE
957
+ path_world_readable_p(VALUE self)
958
+ {
959
+ return rb_funcall(rb_mFileTest, id_world_readable_p, 1, get_strpath(self));
960
+ }
961
+
962
+ /*
963
+ * See FileTest.readable_real?.
964
+ */
965
+ static VALUE
966
+ path_readable_real_p(VALUE self)
967
+ {
968
+ return rb_funcall(rb_mFileTest, id_readable_real_p, 1, get_strpath(self));
969
+ }
970
+
971
+ /*
972
+ * See FileTest.setuid?.
973
+ */
974
+ static VALUE
975
+ path_setuid_p(VALUE self)
976
+ {
977
+ return rb_funcall(rb_mFileTest, id_setuid_p, 1, get_strpath(self));
978
+ }
979
+
980
+ /*
981
+ * See FileTest.setgid?.
982
+ */
983
+ static VALUE
984
+ path_setgid_p(VALUE self)
985
+ {
986
+ return rb_funcall(rb_mFileTest, id_setgid_p, 1, get_strpath(self));
987
+ }
988
+
989
+ /*
990
+ * See FileTest.size.
991
+ */
992
+ static VALUE
993
+ path_size(VALUE self)
994
+ {
995
+ return rb_funcall(rb_mFileTest, id_size, 1, get_strpath(self));
996
+ }
997
+
998
+ /*
999
+ * See FileTest.size?.
1000
+ */
1001
+ static VALUE
1002
+ path_size_p(VALUE self)
1003
+ {
1004
+ return rb_funcall(rb_mFileTest, id_size_p, 1, get_strpath(self));
1005
+ }
1006
+
1007
+ /*
1008
+ * See FileTest.sticky?.
1009
+ */
1010
+ static VALUE
1011
+ path_sticky_p(VALUE self)
1012
+ {
1013
+ return rb_funcall(rb_mFileTest, id_sticky_p, 1, get_strpath(self));
1014
+ }
1015
+
1016
+ /*
1017
+ * See FileTest.symlink?.
1018
+ */
1019
+ static VALUE
1020
+ path_symlink_p(VALUE self)
1021
+ {
1022
+ return rb_funcall(rb_mFileTest, id_symlink_p, 1, get_strpath(self));
1023
+ }
1024
+
1025
+ /*
1026
+ * See FileTest.writable?.
1027
+ */
1028
+ static VALUE
1029
+ path_writable_p(VALUE self)
1030
+ {
1031
+ return rb_funcall(rb_mFileTest, id_writable_p, 1, get_strpath(self));
1032
+ }
1033
+
1034
+ /*
1035
+ * See FileTest.world_writable?.
1036
+ */
1037
+ static VALUE
1038
+ path_world_writable_p(VALUE self)
1039
+ {
1040
+ return rb_funcall(rb_mFileTest, id_world_writable_p, 1, get_strpath(self));
1041
+ }
1042
+
1043
+ /*
1044
+ * See FileTest.writable_real?.
1045
+ */
1046
+ static VALUE
1047
+ path_writable_real_p(VALUE self)
1048
+ {
1049
+ return rb_funcall(rb_mFileTest, id_writable_real_p, 1, get_strpath(self));
1050
+ }
1051
+
1052
+ /*
1053
+ * See FileTest.zero?.
1054
+ */
1055
+ static VALUE
1056
+ path_zero_p(VALUE self)
1057
+ {
1058
+ return rb_funcall(rb_mFileTest, id_zero_p, 1, get_strpath(self));
1059
+ }
1060
+
1061
+ /*
1062
+ * Tests the file is empty.
1063
+ *
1064
+ * See Dir#empty? and FileTest.empty?.
1065
+ */
1066
+ static VALUE
1067
+ path_empty_p(VALUE self)
1068
+ {
1069
+
1070
+ VALUE path = get_strpath(self);
1071
+ if (RTEST(rb_funcall(rb_mFileTest, id_directory_p, 1, path)))
1072
+ return rb_funcall(rb_cDir, id_empty_p, 1, path);
1073
+ else
1074
+ return rb_funcall(rb_mFileTest, id_empty_p, 1, path);
1075
+ }
1076
+
1077
+ static VALUE
1078
+ s_glob_i(RB_BLOCK_CALL_FUNC_ARGLIST(elt, klass))
1079
+ {
1080
+ return rb_yield(rb_class_new_instance(1, &elt, klass));
1081
+ }
1082
+
1083
+ /*
1084
+ * Returns or yields Pathname objects.
1085
+ *
1086
+ * Pathname.glob("lib/i*.rb")
1087
+ * #=> [#<Pathname:lib/ipaddr.rb>, #<Pathname:lib/irb.rb>]
1088
+ *
1089
+ * See Dir.glob.
1090
+ */
1091
+ static VALUE
1092
+ path_s_glob(int argc, VALUE *argv, VALUE klass)
1093
+ {
1094
+ VALUE args[3];
1095
+ int n;
1096
+
1097
+ n = rb_scan_args(argc, argv, "12", &args[0], &args[1], &args[2]);
1098
+ if (rb_block_given_p()) {
1099
+ return rb_block_call_kw(rb_cDir, id_glob, n, args, s_glob_i, klass, RB_PASS_CALLED_KEYWORDS);
1100
+ }
1101
+ else {
1102
+ VALUE ary;
1103
+ long i;
1104
+ ary = rb_funcallv_kw(rb_cDir, id_glob, n, args, RB_PASS_CALLED_KEYWORDS);
1105
+ ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
1106
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
1107
+ VALUE elt = RARRAY_AREF(ary, i);
1108
+ elt = rb_class_new_instance(1, &elt, klass);
1109
+ rb_ary_store(ary, i, elt);
1110
+ }
1111
+ return ary;
1112
+ }
1113
+ }
1114
+
1115
+ static VALUE
1116
+ glob_i(RB_BLOCK_CALL_FUNC_ARGLIST(elt, self))
1117
+ {
1118
+ elt = rb_funcall(self, '+', 1, elt);
1119
+ return rb_yield(elt);
1120
+ }
1121
+
1122
+ /*
1123
+ * Returns or yields Pathname objects.
1124
+ *
1125
+ * Pathname("ruby-2.4.2").glob("R*.md")
1126
+ * #=> [#<Pathname:ruby-2.4.2/README.md>, #<Pathname:ruby-2.4.2/README.ja.md>]
1127
+ *
1128
+ * See Dir.glob.
1129
+ * This method uses the +base+ keyword argument of Dir.glob.
1130
+ */
1131
+ static VALUE
1132
+ path_glob(int argc, VALUE *argv, VALUE self)
1133
+ {
1134
+ VALUE args[3];
1135
+ int n;
1136
+
1137
+ n = rb_scan_args(argc, argv, "11", &args[0], &args[1]);
1138
+ if (n == 1)
1139
+ args[1] = INT2FIX(0);
1140
+
1141
+ args[2] = rb_hash_new();
1142
+ rb_hash_aset(args[2], ID2SYM(id_base), get_strpath(self));
1143
+
1144
+ n = 3;
1145
+
1146
+ if (rb_block_given_p()) {
1147
+ return rb_block_call_kw(rb_cDir, id_glob, n, args, glob_i, self, RB_PASS_KEYWORDS);
1148
+ }
1149
+ else {
1150
+ VALUE ary;
1151
+ long i;
1152
+ ary = rb_funcallv_kw(rb_cDir, id_glob, n, args, RB_PASS_KEYWORDS);
1153
+ ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
1154
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
1155
+ VALUE elt = RARRAY_AREF(ary, i);
1156
+ elt = rb_funcall(self, '+', 1, elt);
1157
+ rb_ary_store(ary, i, elt);
1158
+ }
1159
+ return ary;
1160
+ }
1161
+ }
1162
+
1163
+ /*
1164
+ * Returns the current working directory as a Pathname.
1165
+ *
1166
+ * Pathname.getwd
1167
+ * #=> #<Pathname:/home/zzak/projects/ruby>
1168
+ *
1169
+ * See Dir.getwd.
1170
+ */
1171
+ static VALUE
1172
+ path_s_getwd(VALUE klass)
1173
+ {
1174
+ VALUE str;
1175
+ str = rb_funcall(rb_cDir, id_getwd, 0);
1176
+ return rb_class_new_instance(1, &str, klass);
1177
+ }
1178
+
1179
+ /*
1180
+ * Return the entries (files and subdirectories) in the directory, each as a
1181
+ * Pathname object.
1182
+ *
1183
+ * The results contains just the names in the directory, without any trailing
1184
+ * slashes or recursive look-up.
1185
+ *
1186
+ * pp Pathname.new('/usr/local').entries
1187
+ * #=> [#<Pathname:share>,
1188
+ * # #<Pathname:lib>,
1189
+ * # #<Pathname:..>,
1190
+ * # #<Pathname:include>,
1191
+ * # #<Pathname:etc>,
1192
+ * # #<Pathname:bin>,
1193
+ * # #<Pathname:man>,
1194
+ * # #<Pathname:games>,
1195
+ * # #<Pathname:.>,
1196
+ * # #<Pathname:sbin>,
1197
+ * # #<Pathname:src>]
1198
+ *
1199
+ * The result may contain the current directory <code>#<Pathname:.></code> and
1200
+ * the parent directory <code>#<Pathname:..></code>.
1201
+ *
1202
+ * If you don't want +.+ and +..+ and
1203
+ * want directories, consider Pathname#children.
1204
+ */
1205
+ static VALUE
1206
+ path_entries(VALUE self)
1207
+ {
1208
+ VALUE klass, str, ary;
1209
+ long i;
1210
+ klass = rb_obj_class(self);
1211
+ str = get_strpath(self);
1212
+ ary = rb_funcall(rb_cDir, id_entries, 1, str);
1213
+ ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
1214
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
1215
+ VALUE elt = RARRAY_AREF(ary, i);
1216
+ elt = rb_class_new_instance(1, &elt, klass);
1217
+ rb_ary_store(ary, i, elt);
1218
+ }
1219
+ return ary;
1220
+ }
1221
+
1222
+ /*
1223
+ * Create the referenced directory.
1224
+ *
1225
+ * See Dir.mkdir.
1226
+ */
1227
+ static VALUE
1228
+ path_mkdir(int argc, VALUE *argv, VALUE self)
1229
+ {
1230
+ VALUE str = get_strpath(self);
1231
+ VALUE vmode;
1232
+ if (rb_scan_args(argc, argv, "01", &vmode) == 0)
1233
+ return rb_funcall(rb_cDir, id_mkdir, 1, str);
1234
+ else
1235
+ return rb_funcall(rb_cDir, id_mkdir, 2, str, vmode);
1236
+ }
1237
+
1238
+ /*
1239
+ * Remove the referenced directory.
1240
+ *
1241
+ * See Dir.rmdir.
1242
+ */
1243
+ static VALUE
1244
+ path_rmdir(VALUE self)
1245
+ {
1246
+ return rb_funcall(rb_cDir, id_rmdir, 1, get_strpath(self));
1247
+ }
1248
+
1249
+ /*
1250
+ * Opens the referenced directory.
1251
+ *
1252
+ * See Dir.open.
1253
+ */
1254
+ static VALUE
1255
+ path_opendir(VALUE self)
1256
+ {
1257
+ VALUE args[1];
1258
+
1259
+ args[0] = get_strpath(self);
1260
+ return rb_block_call(rb_cDir, id_open, 1, args, 0, 0);
1261
+ }
1262
+
1263
+ static VALUE
1264
+ each_entry_i(RB_BLOCK_CALL_FUNC_ARGLIST(elt, klass))
1265
+ {
1266
+ return rb_yield(rb_class_new_instance(1, &elt, klass));
1267
+ }
1268
+
1269
+ /*
1270
+ * Iterates over the entries (files and subdirectories) in the directory,
1271
+ * yielding a Pathname object for each entry.
1272
+ */
1273
+ static VALUE
1274
+ path_each_entry(VALUE self)
1275
+ {
1276
+ VALUE args[1];
1277
+
1278
+ args[0] = get_strpath(self);
1279
+ return rb_block_call(rb_cDir, id_foreach, 1, args, each_entry_i, rb_obj_class(self));
1280
+ }
1281
+
1282
+ static VALUE
1283
+ unlink_body(VALUE str)
1284
+ {
1285
+ return rb_funcall(rb_cDir, id_unlink, 1, str);
1286
+ }
1287
+
1288
+ static VALUE
1289
+ unlink_rescue(VALUE str, VALUE errinfo)
1290
+ {
1291
+ return rb_funcall(rb_cFile, id_unlink, 1, str);
1292
+ }
1293
+
1294
+ /*
1295
+ * Removes a file or directory, using File.unlink if +self+ is a file, or
1296
+ * Dir.unlink as necessary.
1297
+ */
1298
+ static VALUE
1299
+ path_unlink(VALUE self)
1300
+ {
1301
+ VALUE eENOTDIR = rb_const_get_at(rb_mErrno, id_ENOTDIR);
1302
+ VALUE str = get_strpath(self);
1303
+ return rb_rescue2(unlink_body, str, unlink_rescue, str, eENOTDIR, (VALUE)0);
1304
+ }
1305
+
1306
+ /*
1307
+ * :call-seq:
1308
+ * Pathname(path) -> pathname
1309
+ *
1310
+ * Creates a new Pathname object from the given string, +path+, and returns
1311
+ * pathname object.
1312
+ *
1313
+ * In order to use this constructor, you must first require the Pathname
1314
+ * standard library extension.
1315
+ *
1316
+ * require 'pathname'
1317
+ * Pathname("/home/zzak")
1318
+ * #=> #<Pathname:/home/zzak>
1319
+ *
1320
+ * See also Pathname::new for more information.
1321
+ */
1322
+ static VALUE
1323
+ path_f_pathname(VALUE self, VALUE str)
1324
+ {
1325
+ if (CLASS_OF(str) == rb_cPathname)
1326
+ return str;
1327
+ return rb_class_new_instance(1, &str, rb_cPathname);
1328
+ }
1329
+
1330
+ /*
1331
+ *
1332
+ * Pathname represents the name of a file or directory on the filesystem,
1333
+ * but not the file itself.
1334
+ *
1335
+ * The pathname depends on the Operating System: Unix, Windows, etc.
1336
+ * This library works with pathnames of local OS, however non-Unix pathnames
1337
+ * are supported experimentally.
1338
+ *
1339
+ * A Pathname can be relative or absolute. It's not until you try to
1340
+ * reference the file that it even matters whether the file exists or not.
1341
+ *
1342
+ * Pathname is immutable. It has no method for destructive update.
1343
+ *
1344
+ * The goal of this class is to manipulate file path information in a neater
1345
+ * way than standard Ruby provides. The examples below demonstrate the
1346
+ * difference.
1347
+ *
1348
+ * *All* functionality from File, FileTest, and some from Dir and FileUtils is
1349
+ * included, in an unsurprising way. It is essentially a facade for all of
1350
+ * these, and more.
1351
+ *
1352
+ * == Examples
1353
+ *
1354
+ * === Example 1: Using Pathname
1355
+ *
1356
+ * require 'pathname'
1357
+ * pn = Pathname.new("/usr/bin/ruby")
1358
+ * size = pn.size # 27662
1359
+ * isdir = pn.directory? # false
1360
+ * dir = pn.dirname # Pathname:/usr/bin
1361
+ * base = pn.basename # Pathname:ruby
1362
+ * dir, base = pn.split # [Pathname:/usr/bin, Pathname:ruby]
1363
+ * data = pn.read
1364
+ * pn.open { |f| _ }
1365
+ * pn.each_line { |line| _ }
1366
+ *
1367
+ * === Example 2: Using standard Ruby
1368
+ *
1369
+ * pn = "/usr/bin/ruby"
1370
+ * size = File.size(pn) # 27662
1371
+ * isdir = File.directory?(pn) # false
1372
+ * dir = File.dirname(pn) # "/usr/bin"
1373
+ * base = File.basename(pn) # "ruby"
1374
+ * dir, base = File.split(pn) # ["/usr/bin", "ruby"]
1375
+ * data = File.read(pn)
1376
+ * File.open(pn) { |f| _ }
1377
+ * File.foreach(pn) { |line| _ }
1378
+ *
1379
+ * === Example 3: Special features
1380
+ *
1381
+ * p1 = Pathname.new("/usr/lib") # Pathname:/usr/lib
1382
+ * p2 = p1 + "ruby/1.8" # Pathname:/usr/lib/ruby/1.8
1383
+ * p3 = p1.parent # Pathname:/usr
1384
+ * p4 = p2.relative_path_from(p3) # Pathname:lib/ruby/1.8
1385
+ * pwd = Pathname.pwd # Pathname:/home/gavin
1386
+ * pwd.absolute? # true
1387
+ * p5 = Pathname.new "." # Pathname:.
1388
+ * p5 = p5 + "music/../articles" # Pathname:music/../articles
1389
+ * p5.cleanpath # Pathname:articles
1390
+ * p5.realpath # Pathname:/home/gavin/articles
1391
+ * p5.children # [Pathname:/home/gavin/articles/linux, ...]
1392
+ *
1393
+ * == Breakdown of functionality
1394
+ *
1395
+ * === Core methods
1396
+ *
1397
+ * These methods are effectively manipulating a String, because that's
1398
+ * all a path is. None of these access the file system except for
1399
+ * #mountpoint?, #children, #each_child, #realdirpath and #realpath.
1400
+ *
1401
+ * - +
1402
+ * - #join
1403
+ * - #parent
1404
+ * - #root?
1405
+ * - #absolute?
1406
+ * - #relative?
1407
+ * - #relative_path_from
1408
+ * - #each_filename
1409
+ * - #cleanpath
1410
+ * - #realpath
1411
+ * - #realdirpath
1412
+ * - #children
1413
+ * - #each_child
1414
+ * - #mountpoint?
1415
+ *
1416
+ * === File status predicate methods
1417
+ *
1418
+ * These methods are a facade for FileTest:
1419
+ * - #blockdev?
1420
+ * - #chardev?
1421
+ * - #directory?
1422
+ * - #executable?
1423
+ * - #executable_real?
1424
+ * - #exist?
1425
+ * - #file?
1426
+ * - #grpowned?
1427
+ * - #owned?
1428
+ * - #pipe?
1429
+ * - #readable?
1430
+ * - #world_readable?
1431
+ * - #readable_real?
1432
+ * - #setgid?
1433
+ * - #setuid?
1434
+ * - #size
1435
+ * - #size?
1436
+ * - #socket?
1437
+ * - #sticky?
1438
+ * - #symlink?
1439
+ * - #writable?
1440
+ * - #world_writable?
1441
+ * - #writable_real?
1442
+ * - #zero?
1443
+ *
1444
+ * === File property and manipulation methods
1445
+ *
1446
+ * These methods are a facade for File:
1447
+ * - #atime
1448
+ * - #birthtime
1449
+ * - #ctime
1450
+ * - #mtime
1451
+ * - #chmod(mode)
1452
+ * - #lchmod(mode)
1453
+ * - #chown(owner, group)
1454
+ * - #lchown(owner, group)
1455
+ * - #fnmatch(pattern, *args)
1456
+ * - #fnmatch?(pattern, *args)
1457
+ * - #ftype
1458
+ * - #make_link(old)
1459
+ * - #open(*args, &block)
1460
+ * - #readlink
1461
+ * - #rename(to)
1462
+ * - #stat
1463
+ * - #lstat
1464
+ * - #make_symlink(old)
1465
+ * - #truncate(length)
1466
+ * - #utime(atime, mtime)
1467
+ * - #basename(*args)
1468
+ * - #dirname
1469
+ * - #extname
1470
+ * - #expand_path(*args)
1471
+ * - #split
1472
+ *
1473
+ * === Directory methods
1474
+ *
1475
+ * These methods are a facade for Dir:
1476
+ * - Pathname.glob(*args)
1477
+ * - Pathname.getwd / Pathname.pwd
1478
+ * - #rmdir
1479
+ * - #entries
1480
+ * - #each_entry(&block)
1481
+ * - #mkdir(*args)
1482
+ * - #opendir(*args)
1483
+ *
1484
+ * === IO
1485
+ *
1486
+ * These methods are a facade for IO:
1487
+ * - #each_line(*args, &block)
1488
+ * - #read(*args)
1489
+ * - #binread(*args)
1490
+ * - #readlines(*args)
1491
+ * - #sysopen(*args)
1492
+ * - #write(*args)
1493
+ * - #binwrite(*args)
1494
+ *
1495
+ * === Utilities
1496
+ *
1497
+ * These methods are a mixture of Find, FileUtils, and others:
1498
+ * - #find(&block)
1499
+ * - #mkpath
1500
+ * - #rmtree
1501
+ * - #unlink / #delete
1502
+ *
1503
+ *
1504
+ * == Method documentation
1505
+ *
1506
+ * As the above section shows, most of the methods in Pathname are facades. The
1507
+ * documentation for these methods generally just says, for instance, "See
1508
+ * FileTest.writable?", as you should be familiar with the original method
1509
+ * anyway, and its documentation (e.g. through +ri+) will contain more
1510
+ * information. In some cases, a brief description will follow.
1511
+ */
1512
+ void
1513
+ Init_pathname(void)
1514
+ {
1515
+ InitVM(pathname);
1516
+
1517
+ rb_cPathname = rb_define_class("Pathname", rb_cObject);
1518
+ rb_define_method(rb_cPathname, "initialize", path_initialize, 1);
1519
+ rb_define_method(rb_cPathname, "freeze", path_freeze, 0);
1520
+ rb_define_method(rb_cPathname, "taint", path_taint, 0);
1521
+ rb_define_method(rb_cPathname, "untaint", path_untaint, 0);
1522
+ rb_define_method(rb_cPathname, "==", path_eq, 1);
1523
+ rb_define_method(rb_cPathname, "===", path_eq, 1);
1524
+ rb_define_method(rb_cPathname, "eql?", path_eq, 1);
1525
+ rb_define_method(rb_cPathname, "<=>", path_cmp, 1);
1526
+ rb_define_method(rb_cPathname, "hash", path_hash, 0);
1527
+ rb_define_method(rb_cPathname, "to_s", path_to_s, 0);
1528
+ rb_define_method(rb_cPathname, "to_path", path_to_s, 0);
1529
+ rb_define_method(rb_cPathname, "inspect", path_inspect, 0);
1530
+ rb_define_method(rb_cPathname, "sub", path_sub, -1);
1531
+ rb_define_method(rb_cPathname, "sub_ext", path_sub_ext, 1);
1532
+ rb_define_method(rb_cPathname, "realpath", path_realpath, -1);
1533
+ rb_define_method(rb_cPathname, "realdirpath", path_realdirpath, -1);
1534
+ rb_define_method(rb_cPathname, "each_line", path_each_line, -1);
1535
+ rb_define_method(rb_cPathname, "read", path_read, -1);
1536
+ rb_define_method(rb_cPathname, "binread", path_binread, -1);
1537
+ rb_define_method(rb_cPathname, "readlines", path_readlines, -1);
1538
+ rb_define_method(rb_cPathname, "write", path_write, -1);
1539
+ rb_define_method(rb_cPathname, "binwrite", path_binwrite, -1);
1540
+ rb_define_method(rb_cPathname, "sysopen", path_sysopen, -1);
1541
+ rb_define_method(rb_cPathname, "atime", path_atime, 0);
1542
+ rb_define_method(rb_cPathname, "birthtime", path_birthtime, 0);
1543
+ rb_define_method(rb_cPathname, "ctime", path_ctime, 0);
1544
+ rb_define_method(rb_cPathname, "mtime", path_mtime, 0);
1545
+ rb_define_method(rb_cPathname, "chmod", path_chmod, 1);
1546
+ rb_define_method(rb_cPathname, "lchmod", path_lchmod, 1);
1547
+ rb_define_method(rb_cPathname, "chown", path_chown, 2);
1548
+ rb_define_method(rb_cPathname, "lchown", path_lchown, 2);
1549
+ rb_define_method(rb_cPathname, "fnmatch", path_fnmatch, -1);
1550
+ rb_define_method(rb_cPathname, "fnmatch?", path_fnmatch, -1);
1551
+ rb_define_method(rb_cPathname, "ftype", path_ftype, 0);
1552
+ rb_define_method(rb_cPathname, "make_link", path_make_link, 1);
1553
+ rb_define_method(rb_cPathname, "open", path_open, -1);
1554
+ rb_define_method(rb_cPathname, "readlink", path_readlink, 0);
1555
+ rb_define_method(rb_cPathname, "rename", path_rename, 1);
1556
+ rb_define_method(rb_cPathname, "stat", path_stat, 0);
1557
+ rb_define_method(rb_cPathname, "lstat", path_lstat, 0);
1558
+ rb_define_method(rb_cPathname, "make_symlink", path_make_symlink, 1);
1559
+ rb_define_method(rb_cPathname, "truncate", path_truncate, 1);
1560
+ rb_define_method(rb_cPathname, "utime", path_utime, 2);
1561
+ rb_define_method(rb_cPathname, "basename", path_basename, -1);
1562
+ rb_define_method(rb_cPathname, "dirname", path_dirname, 0);
1563
+ rb_define_method(rb_cPathname, "extname", path_extname, 0);
1564
+ rb_define_method(rb_cPathname, "expand_path", path_expand_path, -1);
1565
+ rb_define_method(rb_cPathname, "split", path_split, 0);
1566
+ rb_define_method(rb_cPathname, "blockdev?", path_blockdev_p, 0);
1567
+ rb_define_method(rb_cPathname, "chardev?", path_chardev_p, 0);
1568
+ rb_define_method(rb_cPathname, "executable?", path_executable_p, 0);
1569
+ rb_define_method(rb_cPathname, "executable_real?", path_executable_real_p, 0);
1570
+ rb_define_method(rb_cPathname, "exist?", path_exist_p, 0);
1571
+ rb_define_method(rb_cPathname, "grpowned?", path_grpowned_p, 0);
1572
+ rb_define_method(rb_cPathname, "directory?", path_directory_p, 0);
1573
+ rb_define_method(rb_cPathname, "file?", path_file_p, 0);
1574
+ rb_define_method(rb_cPathname, "pipe?", path_pipe_p, 0);
1575
+ rb_define_method(rb_cPathname, "socket?", path_socket_p, 0);
1576
+ rb_define_method(rb_cPathname, "owned?", path_owned_p, 0);
1577
+ rb_define_method(rb_cPathname, "readable?", path_readable_p, 0);
1578
+ rb_define_method(rb_cPathname, "world_readable?", path_world_readable_p, 0);
1579
+ rb_define_method(rb_cPathname, "readable_real?", path_readable_real_p, 0);
1580
+ rb_define_method(rb_cPathname, "setuid?", path_setuid_p, 0);
1581
+ rb_define_method(rb_cPathname, "setgid?", path_setgid_p, 0);
1582
+ rb_define_method(rb_cPathname, "size", path_size, 0);
1583
+ rb_define_method(rb_cPathname, "size?", path_size_p, 0);
1584
+ rb_define_method(rb_cPathname, "sticky?", path_sticky_p, 0);
1585
+ rb_define_method(rb_cPathname, "symlink?", path_symlink_p, 0);
1586
+ rb_define_method(rb_cPathname, "writable?", path_writable_p, 0);
1587
+ rb_define_method(rb_cPathname, "world_writable?", path_world_writable_p, 0);
1588
+ rb_define_method(rb_cPathname, "writable_real?", path_writable_real_p, 0);
1589
+ rb_define_method(rb_cPathname, "zero?", path_zero_p, 0);
1590
+ rb_define_method(rb_cPathname, "empty?", path_empty_p, 0);
1591
+ rb_define_singleton_method(rb_cPathname, "glob", path_s_glob, -1);
1592
+ rb_define_singleton_method(rb_cPathname, "getwd", path_s_getwd, 0);
1593
+ rb_define_singleton_method(rb_cPathname, "pwd", path_s_getwd, 0);
1594
+ rb_define_method(rb_cPathname, "glob", path_glob, -1);
1595
+ rb_define_method(rb_cPathname, "entries", path_entries, 0);
1596
+ rb_define_method(rb_cPathname, "mkdir", path_mkdir, -1);
1597
+ rb_define_method(rb_cPathname, "rmdir", path_rmdir, 0);
1598
+ rb_define_method(rb_cPathname, "opendir", path_opendir, 0);
1599
+ rb_define_method(rb_cPathname, "each_entry", path_each_entry, 0);
1600
+ rb_define_method(rb_cPathname, "unlink", path_unlink, 0);
1601
+ rb_define_method(rb_cPathname, "delete", path_unlink, 0);
1602
+ rb_undef_method(rb_cPathname, "=~");
1603
+ rb_define_global_function("Pathname", path_f_pathname, 1);
1604
+ }
1605
+
1606
+ void
1607
+ InitVM_pathname(void)
1608
+ {
1609
+ #undef rb_intern
1610
+ id_at_path = rb_intern("@path");
1611
+ id_to_path = rb_intern("to_path");
1612
+ id_ENOTDIR = rb_intern("ENOTDIR");
1613
+ id_atime = rb_intern("atime");
1614
+ id_basename = rb_intern("basename");
1615
+ id_base = rb_intern("base");
1616
+ id_binread = rb_intern("binread");
1617
+ id_binwrite = rb_intern("binwrite");
1618
+ id_birthtime = rb_intern("birthtime");
1619
+ id_blockdev_p = rb_intern("blockdev?");
1620
+ id_chardev_p = rb_intern("chardev?");
1621
+ id_chmod = rb_intern("chmod");
1622
+ id_chown = rb_intern("chown");
1623
+ id_ctime = rb_intern("ctime");
1624
+ id_directory_p = rb_intern("directory?");
1625
+ id_dirname = rb_intern("dirname");
1626
+ id_empty_p = rb_intern("empty?");
1627
+ id_entries = rb_intern("entries");
1628
+ id_executable_p = rb_intern("executable?");
1629
+ id_executable_real_p = rb_intern("executable_real?");
1630
+ id_exist_p = rb_intern("exist?");
1631
+ id_expand_path = rb_intern("expand_path");
1632
+ id_extname = rb_intern("extname");
1633
+ id_file_p = rb_intern("file?");
1634
+ id_fnmatch = rb_intern("fnmatch");
1635
+ id_foreach = rb_intern("foreach");
1636
+ id_ftype = rb_intern("ftype");
1637
+ id_getwd = rb_intern("getwd");
1638
+ id_glob = rb_intern("glob");
1639
+ id_grpowned_p = rb_intern("grpowned?");
1640
+ id_lchmod = rb_intern("lchmod");
1641
+ id_lchown = rb_intern("lchown");
1642
+ id_link = rb_intern("link");
1643
+ id_lstat = rb_intern("lstat");
1644
+ id_mkdir = rb_intern("mkdir");
1645
+ id_mtime = rb_intern("mtime");
1646
+ id_open = rb_intern("open");
1647
+ id_owned_p = rb_intern("owned?");
1648
+ id_pipe_p = rb_intern("pipe?");
1649
+ id_read = rb_intern("read");
1650
+ id_readable_p = rb_intern("readable?");
1651
+ id_readable_real_p = rb_intern("readable_real?");
1652
+ id_readlines = rb_intern("readlines");
1653
+ id_readlink = rb_intern("readlink");
1654
+ id_realdirpath = rb_intern("realdirpath");
1655
+ id_realpath = rb_intern("realpath");
1656
+ id_rename = rb_intern("rename");
1657
+ id_rmdir = rb_intern("rmdir");
1658
+ id_setgid_p = rb_intern("setgid?");
1659
+ id_setuid_p = rb_intern("setuid?");
1660
+ id_size = rb_intern("size");
1661
+ id_size_p = rb_intern("size?");
1662
+ id_socket_p = rb_intern("socket?");
1663
+ id_split = rb_intern("split");
1664
+ id_stat = rb_intern("stat");
1665
+ id_sticky_p = rb_intern("sticky?");
1666
+ id_sub = rb_intern("sub");
1667
+ id_symlink = rb_intern("symlink");
1668
+ id_symlink_p = rb_intern("symlink?");
1669
+ id_sysopen = rb_intern("sysopen");
1670
+ id_truncate = rb_intern("truncate");
1671
+ id_unlink = rb_intern("unlink");
1672
+ id_utime = rb_intern("utime");
1673
+ id_world_readable_p = rb_intern("world_readable?");
1674
+ id_world_writable_p = rb_intern("world_writable?");
1675
+ id_writable_p = rb_intern("writable?");
1676
+ id_writable_real_p = rb_intern("writable_real?");
1677
+ id_write = rb_intern("write");
1678
+ id_zero_p = rb_intern("zero?");
1679
+ }