Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 #include "ruby.h" 00002 #include "ruby/encoding.h" 00003 00004 static VALUE rb_cPathname; 00005 static ID id_at_path, id_to_path; 00006 00007 static VALUE 00008 get_strpath(VALUE obj) 00009 { 00010 VALUE strpath; 00011 strpath = rb_ivar_get(obj, id_at_path); 00012 if (!RB_TYPE_P(strpath, T_STRING)) 00013 rb_raise(rb_eTypeError, "unexpected @path"); 00014 return strpath; 00015 } 00016 00017 static void 00018 set_strpath(VALUE obj, VALUE val) 00019 { 00020 rb_ivar_set(obj, id_at_path, val); 00021 } 00022 00023 /* 00024 * Create a Pathname object from the given String (or String-like object). 00025 * If +path+ contains a NULL character (<tt>\0</tt>), an ArgumentError is raised. 00026 */ 00027 static VALUE 00028 path_initialize(VALUE self, VALUE arg) 00029 { 00030 VALUE str; 00031 if (RB_TYPE_P(arg, T_STRING)) { 00032 str = arg; 00033 } 00034 else { 00035 str = rb_check_funcall(arg, id_to_path, 0, NULL); 00036 if (str == Qundef) 00037 str = arg; 00038 StringValue(str); 00039 } 00040 if (memchr(RSTRING_PTR(str), '\0', RSTRING_LEN(str))) 00041 rb_raise(rb_eArgError, "pathname contains null byte"); 00042 str = rb_obj_dup(str); 00043 00044 set_strpath(self, str); 00045 OBJ_INFECT(self, str); 00046 return self; 00047 } 00048 00049 /* 00050 * call-seq: 00051 * pathname.freeze -> obj 00052 * 00053 * Freezes this Pathname. 00054 * 00055 * See Object.freeze. 00056 */ 00057 static VALUE 00058 path_freeze(VALUE self) 00059 { 00060 rb_call_super(0, 0); 00061 rb_str_freeze(get_strpath(self)); 00062 return self; 00063 } 00064 00065 /* 00066 * call-seq: 00067 * pathname.taint -> obj 00068 * 00069 * Taints this Pathname. 00070 * 00071 * See Object.taint. 00072 */ 00073 static VALUE 00074 path_taint(VALUE self) 00075 { 00076 rb_call_super(0, 0); 00077 rb_obj_taint(get_strpath(self)); 00078 return self; 00079 } 00080 00081 /* 00082 * call-seq: 00083 * pathname.untaint -> obj 00084 * 00085 * Untaints this Pathname. 00086 * 00087 * See Object.untaint. 00088 */ 00089 static VALUE 00090 path_untaint(VALUE self) 00091 { 00092 rb_call_super(0, 0); 00093 rb_obj_untaint(get_strpath(self)); 00094 return self; 00095 } 00096 00097 /* 00098 * Compare this pathname with +other+. The comparison is string-based. 00099 * Be aware that two different paths (<tt>foo.txt</tt> and <tt>./foo.txt</tt>) 00100 * can refer to the same file. 00101 */ 00102 static VALUE 00103 path_eq(VALUE self, VALUE other) 00104 { 00105 if (!rb_obj_is_kind_of(other, rb_cPathname)) 00106 return Qfalse; 00107 return rb_str_equal(get_strpath(self), get_strpath(other)); 00108 } 00109 00110 /* 00111 * Provides a case-sensitive comparison operator for pathnames. 00112 * 00113 * Pathname.new('/usr') <=> Pathname.new('/usr/bin') 00114 * #=> -1 00115 * Pathname.new('/usr/bin') <=> Pathname.new('/usr/bin') 00116 * #=> 0 00117 * Pathname.new('/usr/bin') <=> Pathname.new('/USR/BIN') 00118 * #=> 1 00119 * 00120 * It will return +-1+, +0+ or +1+ depending on the value of the left argument 00121 * relative to the right argument. Or it will return +nil+ if the arguments 00122 * are not comparable. 00123 */ 00124 static VALUE 00125 path_cmp(VALUE self, VALUE other) 00126 { 00127 VALUE s1, s2; 00128 char *p1, *p2; 00129 char *e1, *e2; 00130 if (!rb_obj_is_kind_of(other, rb_cPathname)) 00131 return Qnil; 00132 s1 = get_strpath(self); 00133 s2 = get_strpath(other); 00134 p1 = RSTRING_PTR(s1); 00135 p2 = RSTRING_PTR(s2); 00136 e1 = p1 + RSTRING_LEN(s1); 00137 e2 = p2 + RSTRING_LEN(s2); 00138 while (p1 < e1 && p2 < e2) { 00139 int c1, c2; 00140 c1 = (unsigned char)*p1++; 00141 c2 = (unsigned char)*p2++; 00142 if (c1 == '/') c1 = '\0'; 00143 if (c2 == '/') c2 = '\0'; 00144 if (c1 != c2) { 00145 if (c1 < c2) 00146 return INT2FIX(-1); 00147 else 00148 return INT2FIX(1); 00149 } 00150 } 00151 if (p1 < e1) 00152 return INT2FIX(1); 00153 if (p2 < e2) 00154 return INT2FIX(-1); 00155 return INT2FIX(0); 00156 } 00157 00158 /* :nodoc: */ 00159 static VALUE 00160 path_hash(VALUE self) 00161 { 00162 return INT2FIX(rb_str_hash(get_strpath(self))); 00163 } 00164 00165 /* 00166 * call-seq: 00167 * pathname.to_s -> string 00168 * pathname.to_path -> string 00169 * 00170 * Return the path as a String. 00171 * 00172 * to_path is implemented so Pathname objects are usable with File.open, etc. 00173 */ 00174 static VALUE 00175 path_to_s(VALUE self) 00176 { 00177 return rb_obj_dup(get_strpath(self)); 00178 } 00179 00180 /* :nodoc: */ 00181 static VALUE 00182 path_inspect(VALUE self) 00183 { 00184 const char *c = rb_obj_classname(self); 00185 VALUE str = get_strpath(self); 00186 return rb_sprintf("#<%s:%s>", c, RSTRING_PTR(str)); 00187 } 00188 00189 /* 00190 * Return a pathname which is substituted by String#sub. 00191 * 00192 * path1 = Pathname.new('/usr/bin/perl') 00193 * path1.sub('perl', 'ruby') 00194 * #=> #<Pathname:/usr/bin/ruby> 00195 */ 00196 static VALUE 00197 path_sub(int argc, VALUE *argv, VALUE self) 00198 { 00199 VALUE str = get_strpath(self); 00200 00201 if (rb_block_given_p()) { 00202 str = rb_block_call(str, rb_intern("sub"), argc, argv, 0, 0); 00203 } 00204 else { 00205 str = rb_funcall2(str, rb_intern("sub"), argc, argv); 00206 } 00207 return rb_class_new_instance(1, &str, rb_obj_class(self)); 00208 } 00209 00210 /* 00211 * Return a pathname with +repl+ added as a suffix to the basename. 00212 * 00213 * If self has no extension part, +repl+ is appended. 00214 * 00215 * Pathname.new('/usr/bin/shutdown').sub_ext('.rb') 00216 * #=> #<Pathname:/usr/bin/shutdown.rb> 00217 */ 00218 static VALUE 00219 path_sub_ext(VALUE self, VALUE repl) 00220 { 00221 VALUE str = get_strpath(self); 00222 VALUE str2; 00223 long extlen; 00224 const char *ext; 00225 const char *p; 00226 00227 StringValue(repl); 00228 p = RSTRING_PTR(str); 00229 extlen = RSTRING_LEN(str); 00230 ext = ruby_enc_find_extname(p, &extlen, rb_enc_get(str)); 00231 if (ext == NULL) { 00232 ext = p + RSTRING_LEN(str); 00233 } 00234 else if (extlen <= 1) { 00235 ext += extlen; 00236 } 00237 str2 = rb_str_subseq(str, 0, ext-p); 00238 rb_str_append(str2, repl); 00239 OBJ_INFECT(str2, str); 00240 return rb_class_new_instance(1, &str2, rb_obj_class(self)); 00241 } 00242 00243 /* Facade for File */ 00244 00245 /* 00246 * Returns the real (absolute) pathname for +self+ in the actual 00247 * filesystem. 00248 * 00249 * Does not contain symlinks or useless dots, +..+ and +.+. 00250 * 00251 * All components of the pathname must exist when this method is 00252 * called. 00253 * 00254 */ 00255 static VALUE 00256 path_realpath(int argc, VALUE *argv, VALUE self) 00257 { 00258 VALUE basedir, str; 00259 rb_scan_args(argc, argv, "01", &basedir); 00260 str = rb_funcall(rb_cFile, rb_intern("realpath"), 2, get_strpath(self), basedir); 00261 return rb_class_new_instance(1, &str, rb_obj_class(self)); 00262 } 00263 00264 /* 00265 * Returns the real (absolute) pathname of +self+ in the actual filesystem. 00266 * 00267 * Does not contain symlinks or useless dots, +..+ and +.+. 00268 * 00269 * The last component of the real pathname can be nonexistent. 00270 */ 00271 static VALUE 00272 path_realdirpath(int argc, VALUE *argv, VALUE self) 00273 { 00274 VALUE basedir, str; 00275 rb_scan_args(argc, argv, "01", &basedir); 00276 str = rb_funcall(rb_cFile, rb_intern("realdirpath"), 2, get_strpath(self), basedir); 00277 return rb_class_new_instance(1, &str, rb_obj_class(self)); 00278 } 00279 00280 /* 00281 * call-seq: 00282 * pathname.each_line {|line| ... } 00283 * pathname.each_line(sep=$/ [, open_args]) {|line| block } -> nil 00284 * pathname.each_line(limit [, open_args]) {|line| block } -> nil 00285 * pathname.each_line(sep, limit [, open_args]) {|line| block } -> nil 00286 * pathname.each_line(...) -> an_enumerator 00287 * 00288 * Iterates over each line in the file and yields a String object for each. 00289 */ 00290 static VALUE 00291 path_each_line(int argc, VALUE *argv, VALUE self) 00292 { 00293 VALUE args[4]; 00294 int n; 00295 00296 args[0] = get_strpath(self); 00297 n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]); 00298 if (rb_block_given_p()) { 00299 return rb_block_call(rb_cIO, rb_intern("foreach"), 1+n, args, 0, 0); 00300 } 00301 else { 00302 return rb_funcall2(rb_cIO, rb_intern("foreach"), 1+n, args); 00303 } 00304 } 00305 00306 /* 00307 * call-seq: 00308 * pathname.read([length [, offset]]) -> string 00309 * pathname.read([length [, offset]], open_args) -> string 00310 * 00311 * Returns all data from the file, or the first +N+ bytes if specified. 00312 * 00313 * See IO.read. 00314 * 00315 */ 00316 static VALUE 00317 path_read(int argc, VALUE *argv, VALUE self) 00318 { 00319 VALUE args[4]; 00320 int n; 00321 00322 args[0] = get_strpath(self); 00323 n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]); 00324 return rb_funcall2(rb_cIO, rb_intern("read"), 1+n, args); 00325 } 00326 00327 /* 00328 * call-seq: 00329 * pathname.binread([length [, offset]]) -> string 00330 * 00331 * Returns all the bytes from the file, or the first +N+ if specified. 00332 * 00333 * See IO.binread. 00334 * 00335 */ 00336 static VALUE 00337 path_binread(int argc, VALUE *argv, VALUE self) 00338 { 00339 VALUE args[3]; 00340 int n; 00341 00342 args[0] = get_strpath(self); 00343 n = rb_scan_args(argc, argv, "02", &args[1], &args[2]); 00344 return rb_funcall2(rb_cIO, rb_intern("binread"), 1+n, args); 00345 } 00346 00347 /* 00348 * call-seq: 00349 * pathname.readlines(sep=$/ [, open_args]) -> array 00350 * pathname.readlines(limit [, open_args]) -> array 00351 * pathname.readlines(sep, limit [, open_args]) -> array 00352 * 00353 * Returns all the lines from the file. 00354 * 00355 * See IO.readlines. 00356 * 00357 */ 00358 static VALUE 00359 path_readlines(int argc, VALUE *argv, VALUE self) 00360 { 00361 VALUE args[4]; 00362 int n; 00363 00364 args[0] = get_strpath(self); 00365 n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]); 00366 return rb_funcall2(rb_cIO, rb_intern("readlines"), 1+n, args); 00367 } 00368 00369 /* 00370 * call-seq: 00371 * pathname.sysopen([mode, [perm]]) -> fixnum 00372 * 00373 * See IO.sysopen. 00374 * 00375 */ 00376 static VALUE 00377 path_sysopen(int argc, VALUE *argv, VALUE self) 00378 { 00379 VALUE args[3]; 00380 int n; 00381 00382 args[0] = get_strpath(self); 00383 n = rb_scan_args(argc, argv, "02", &args[1], &args[2]); 00384 return rb_funcall2(rb_cIO, rb_intern("sysopen"), 1+n, args); 00385 } 00386 00387 /* 00388 * call-seq: 00389 * pathname.atime -> time 00390 * 00391 * Returns the last access time for the file. 00392 * 00393 * See File.atime. 00394 */ 00395 static VALUE 00396 path_atime(VALUE self) 00397 { 00398 return rb_funcall(rb_cFile, rb_intern("atime"), 1, get_strpath(self)); 00399 } 00400 00401 /* 00402 * call-seq: 00403 * pathname.ctime -> time 00404 * 00405 * Returns the last change time, using directory information, not the file itself. 00406 * 00407 * See File.ctime. 00408 */ 00409 static VALUE 00410 path_ctime(VALUE self) 00411 { 00412 return rb_funcall(rb_cFile, rb_intern("ctime"), 1, get_strpath(self)); 00413 } 00414 00415 /* 00416 * call-seq: 00417 * pathname.mtime -> time 00418 * 00419 * Returns the last modified time of the file. 00420 * 00421 * See File.mtime. 00422 */ 00423 static VALUE 00424 path_mtime(VALUE self) 00425 { 00426 return rb_funcall(rb_cFile, rb_intern("mtime"), 1, get_strpath(self)); 00427 } 00428 00429 /* 00430 * call-seq: 00431 * pathname.chmod -> integer 00432 * 00433 * Changes file permissions. 00434 * 00435 * See File.chmod. 00436 */ 00437 static VALUE 00438 path_chmod(VALUE self, VALUE mode) 00439 { 00440 return rb_funcall(rb_cFile, rb_intern("chmod"), 2, mode, get_strpath(self)); 00441 } 00442 00443 /* 00444 * call-seq: 00445 * pathname.lchmod -> integer 00446 * 00447 * Same as Pathname.chmod, but does not follow symbolic links. 00448 * 00449 * See File.lchmod. 00450 */ 00451 static VALUE 00452 path_lchmod(VALUE self, VALUE mode) 00453 { 00454 return rb_funcall(rb_cFile, rb_intern("lchmod"), 2, mode, get_strpath(self)); 00455 } 00456 00457 /* 00458 * call-seq: 00459 * pathname.chown -> integer 00460 * 00461 * Change owner and group of the file. 00462 * 00463 * See File.chown. 00464 */ 00465 static VALUE 00466 path_chown(VALUE self, VALUE owner, VALUE group) 00467 { 00468 return rb_funcall(rb_cFile, rb_intern("chown"), 3, owner, group, get_strpath(self)); 00469 } 00470 00471 /* 00472 * call-seq: 00473 * pathname.lchown -> integer 00474 * 00475 * Same as Pathname.chown, but does not follow symbolic links. 00476 * 00477 * See File.lchown. 00478 */ 00479 static VALUE 00480 path_lchown(VALUE self, VALUE owner, VALUE group) 00481 { 00482 return rb_funcall(rb_cFile, rb_intern("lchown"), 3, owner, group, get_strpath(self)); 00483 } 00484 00485 /* 00486 * call-seq: 00487 * pathname.fnmatch(pattern, [flags]) -> string 00488 * pathname.fnmatch?(pattern, [flags]) -> string 00489 * 00490 * Return +true+ if the receiver matches the given pattern. 00491 * 00492 * See File.fnmatch. 00493 */ 00494 static VALUE 00495 path_fnmatch(int argc, VALUE *argv, VALUE self) 00496 { 00497 VALUE str = get_strpath(self); 00498 VALUE pattern, flags; 00499 if (rb_scan_args(argc, argv, "11", &pattern, &flags) == 1) 00500 return rb_funcall(rb_cFile, rb_intern("fnmatch"), 2, pattern, str); 00501 else 00502 return rb_funcall(rb_cFile, rb_intern("fnmatch"), 3, pattern, str, flags); 00503 } 00504 00505 /* 00506 * call-seq: 00507 * pathname.ftype -> string 00508 * 00509 * Returns "type" of file ("file", "directory", etc). 00510 * 00511 * See File.ftype. 00512 */ 00513 static VALUE 00514 path_ftype(VALUE self) 00515 { 00516 return rb_funcall(rb_cFile, rb_intern("ftype"), 1, get_strpath(self)); 00517 } 00518 00519 /* 00520 * call-seq: 00521 * pathname.make_link(old) 00522 * 00523 * Creates a hard link at _pathname_. 00524 * 00525 * See File.link. 00526 */ 00527 static VALUE 00528 path_make_link(VALUE self, VALUE old) 00529 { 00530 return rb_funcall(rb_cFile, rb_intern("link"), 2, old, get_strpath(self)); 00531 } 00532 00533 /* 00534 * Opens the file for reading or writing. 00535 * 00536 * See File.open. 00537 */ 00538 static VALUE 00539 path_open(int argc, VALUE *argv, VALUE self) 00540 { 00541 VALUE args[4]; 00542 int n; 00543 00544 args[0] = get_strpath(self); 00545 n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]); 00546 if (rb_block_given_p()) { 00547 return rb_block_call(rb_cFile, rb_intern("open"), 1+n, args, 0, 0); 00548 } 00549 else { 00550 return rb_funcall2(rb_cFile, rb_intern("open"), 1+n, args); 00551 } 00552 } 00553 00554 /* 00555 * Read symbolic link. 00556 * 00557 * See File.readlink. 00558 */ 00559 static VALUE 00560 path_readlink(VALUE self) 00561 { 00562 VALUE str; 00563 str = rb_funcall(rb_cFile, rb_intern("readlink"), 1, get_strpath(self)); 00564 return rb_class_new_instance(1, &str, rb_obj_class(self)); 00565 } 00566 00567 /* 00568 * Rename the file. 00569 * 00570 * See File.rename. 00571 */ 00572 static VALUE 00573 path_rename(VALUE self, VALUE to) 00574 { 00575 return rb_funcall(rb_cFile, rb_intern("rename"), 2, get_strpath(self), to); 00576 } 00577 00578 /* 00579 * Returns a File::Stat object. 00580 * 00581 * See File.stat. 00582 */ 00583 static VALUE 00584 path_stat(VALUE self) 00585 { 00586 return rb_funcall(rb_cFile, rb_intern("stat"), 1, get_strpath(self)); 00587 } 00588 00589 /* 00590 * See File.lstat. 00591 */ 00592 static VALUE 00593 path_lstat(VALUE self) 00594 { 00595 return rb_funcall(rb_cFile, rb_intern("lstat"), 1, get_strpath(self)); 00596 } 00597 00598 /* 00599 * call-seq: 00600 * pathname.make_symlink(old) 00601 * 00602 * Creates a symbolic link. 00603 * 00604 * See File.symlink. 00605 */ 00606 static VALUE 00607 path_make_symlink(VALUE self, VALUE old) 00608 { 00609 return rb_funcall(rb_cFile, rb_intern("symlink"), 2, old, get_strpath(self)); 00610 } 00611 00612 /* 00613 * Truncates the file to +length+ bytes. 00614 * 00615 * See File.truncate. 00616 */ 00617 static VALUE 00618 path_truncate(VALUE self, VALUE length) 00619 { 00620 return rb_funcall(rb_cFile, rb_intern("truncate"), 2, get_strpath(self), length); 00621 } 00622 00623 /* 00624 * Update the access and modification times of the file. 00625 * 00626 * See File.utime. 00627 */ 00628 static VALUE 00629 path_utime(VALUE self, VALUE atime, VALUE mtime) 00630 { 00631 return rb_funcall(rb_cFile, rb_intern("utime"), 3, atime, mtime, get_strpath(self)); 00632 } 00633 00634 /* 00635 * Returns the last component of the path. 00636 * 00637 * See File.basename. 00638 */ 00639 static VALUE 00640 path_basename(int argc, VALUE *argv, VALUE self) 00641 { 00642 VALUE str = get_strpath(self); 00643 VALUE fext; 00644 if (rb_scan_args(argc, argv, "01", &fext) == 0) 00645 str = rb_funcall(rb_cFile, rb_intern("basename"), 1, str); 00646 else 00647 str = rb_funcall(rb_cFile, rb_intern("basename"), 2, str, fext); 00648 return rb_class_new_instance(1, &str, rb_obj_class(self)); 00649 } 00650 00651 /* 00652 * Returns all but the last component of the path. 00653 * 00654 * See File.dirname. 00655 */ 00656 static VALUE 00657 path_dirname(VALUE self) 00658 { 00659 VALUE str = get_strpath(self); 00660 str = rb_funcall(rb_cFile, rb_intern("dirname"), 1, str); 00661 return rb_class_new_instance(1, &str, rb_obj_class(self)); 00662 } 00663 00664 /* 00665 * Returns the file's extension. 00666 * 00667 * See File.extname. 00668 */ 00669 static VALUE 00670 path_extname(VALUE self) 00671 { 00672 VALUE str = get_strpath(self); 00673 return rb_funcall(rb_cFile, rb_intern("extname"), 1, str); 00674 } 00675 00676 /* 00677 * Returns the absolute path for the file. 00678 * 00679 * See File.expand_path. 00680 */ 00681 static VALUE 00682 path_expand_path(int argc, VALUE *argv, VALUE self) 00683 { 00684 VALUE str = get_strpath(self); 00685 VALUE dname; 00686 if (rb_scan_args(argc, argv, "01", &dname) == 0) 00687 str = rb_funcall(rb_cFile, rb_intern("expand_path"), 1, str); 00688 else 00689 str = rb_funcall(rb_cFile, rb_intern("expand_path"), 2, str, dname); 00690 return rb_class_new_instance(1, &str, rb_obj_class(self)); 00691 } 00692 00693 /* 00694 * Returns the #dirname and the #basename in an Array. 00695 * 00696 * See File.split. 00697 */ 00698 static VALUE 00699 path_split(VALUE self) 00700 { 00701 VALUE str = get_strpath(self); 00702 VALUE ary, dirname, basename; 00703 ary = rb_funcall(rb_cFile, rb_intern("split"), 1, str); 00704 ary = rb_check_array_type(ary); 00705 dirname = rb_ary_entry(ary, 0); 00706 basename = rb_ary_entry(ary, 1); 00707 dirname = rb_class_new_instance(1, &dirname, rb_obj_class(self)); 00708 basename = rb_class_new_instance(1, &basename, rb_obj_class(self)); 00709 return rb_ary_new3(2, dirname, basename); 00710 } 00711 00712 /* 00713 * See FileTest.blockdev?. 00714 */ 00715 static VALUE 00716 path_blockdev_p(VALUE self) 00717 { 00718 return rb_funcall(rb_mFileTest, rb_intern("blockdev?"), 1, get_strpath(self)); 00719 } 00720 00721 /* 00722 * See FileTest.chardev?. 00723 */ 00724 static VALUE 00725 path_chardev_p(VALUE self) 00726 { 00727 return rb_funcall(rb_mFileTest, rb_intern("chardev?"), 1, get_strpath(self)); 00728 } 00729 00730 /* 00731 * See FileTest.executable?. 00732 */ 00733 static VALUE 00734 path_executable_p(VALUE self) 00735 { 00736 return rb_funcall(rb_mFileTest, rb_intern("executable?"), 1, get_strpath(self)); 00737 } 00738 00739 /* 00740 * See FileTest.executable_real?. 00741 */ 00742 static VALUE 00743 path_executable_real_p(VALUE self) 00744 { 00745 return rb_funcall(rb_mFileTest, rb_intern("executable_real?"), 1, get_strpath(self)); 00746 } 00747 00748 /* 00749 * See FileTest.exist?. 00750 */ 00751 static VALUE 00752 path_exist_p(VALUE self) 00753 { 00754 return rb_funcall(rb_mFileTest, rb_intern("exist?"), 1, get_strpath(self)); 00755 } 00756 00757 /* 00758 * See FileTest.grpowned?. 00759 */ 00760 static VALUE 00761 path_grpowned_p(VALUE self) 00762 { 00763 return rb_funcall(rb_mFileTest, rb_intern("grpowned?"), 1, get_strpath(self)); 00764 } 00765 00766 /* 00767 * See FileTest.directory?. 00768 */ 00769 static VALUE 00770 path_directory_p(VALUE self) 00771 { 00772 return rb_funcall(rb_mFileTest, rb_intern("directory?"), 1, get_strpath(self)); 00773 } 00774 00775 /* 00776 * See FileTest.file?. 00777 */ 00778 static VALUE 00779 path_file_p(VALUE self) 00780 { 00781 return rb_funcall(rb_mFileTest, rb_intern("file?"), 1, get_strpath(self)); 00782 } 00783 00784 /* 00785 * See FileTest.pipe?. 00786 */ 00787 static VALUE 00788 path_pipe_p(VALUE self) 00789 { 00790 return rb_funcall(rb_mFileTest, rb_intern("pipe?"), 1, get_strpath(self)); 00791 } 00792 00793 /* 00794 * See FileTest.socket?. 00795 */ 00796 static VALUE 00797 path_socket_p(VALUE self) 00798 { 00799 return rb_funcall(rb_mFileTest, rb_intern("socket?"), 1, get_strpath(self)); 00800 } 00801 00802 /* 00803 * See FileTest.owned?. 00804 */ 00805 static VALUE 00806 path_owned_p(VALUE self) 00807 { 00808 return rb_funcall(rb_mFileTest, rb_intern("owned?"), 1, get_strpath(self)); 00809 } 00810 00811 /* 00812 * See FileTest.readable?. 00813 */ 00814 static VALUE 00815 path_readable_p(VALUE self) 00816 { 00817 return rb_funcall(rb_mFileTest, rb_intern("readable?"), 1, get_strpath(self)); 00818 } 00819 00820 /* 00821 * See FileTest.world_readable?. 00822 */ 00823 static VALUE 00824 path_world_readable_p(VALUE self) 00825 { 00826 return rb_funcall(rb_mFileTest, rb_intern("world_readable?"), 1, get_strpath(self)); 00827 } 00828 00829 /* 00830 * See FileTest.readable_real?. 00831 */ 00832 static VALUE 00833 path_readable_real_p(VALUE self) 00834 { 00835 return rb_funcall(rb_mFileTest, rb_intern("readable_real?"), 1, get_strpath(self)); 00836 } 00837 00838 /* 00839 * See FileTest.setuid?. 00840 */ 00841 static VALUE 00842 path_setuid_p(VALUE self) 00843 { 00844 return rb_funcall(rb_mFileTest, rb_intern("setuid?"), 1, get_strpath(self)); 00845 } 00846 00847 /* 00848 * See FileTest.setgid?. 00849 */ 00850 static VALUE 00851 path_setgid_p(VALUE self) 00852 { 00853 return rb_funcall(rb_mFileTest, rb_intern("setgid?"), 1, get_strpath(self)); 00854 } 00855 00856 /* 00857 * See FileTest.size. 00858 */ 00859 static VALUE 00860 path_size(VALUE self) 00861 { 00862 return rb_funcall(rb_mFileTest, rb_intern("size"), 1, get_strpath(self)); 00863 } 00864 00865 /* 00866 * See FileTest.size?. 00867 */ 00868 static VALUE 00869 path_size_p(VALUE self) 00870 { 00871 return rb_funcall(rb_mFileTest, rb_intern("size?"), 1, get_strpath(self)); 00872 } 00873 00874 /* 00875 * See FileTest.sticky?. 00876 */ 00877 static VALUE 00878 path_sticky_p(VALUE self) 00879 { 00880 return rb_funcall(rb_mFileTest, rb_intern("sticky?"), 1, get_strpath(self)); 00881 } 00882 00883 /* 00884 * See FileTest.symlink?. 00885 */ 00886 static VALUE 00887 path_symlink_p(VALUE self) 00888 { 00889 return rb_funcall(rb_mFileTest, rb_intern("symlink?"), 1, get_strpath(self)); 00890 } 00891 00892 /* 00893 * See FileTest.writable?. 00894 */ 00895 static VALUE 00896 path_writable_p(VALUE self) 00897 { 00898 return rb_funcall(rb_mFileTest, rb_intern("writable?"), 1, get_strpath(self)); 00899 } 00900 00901 /* 00902 * See FileTest.world_writable?. 00903 */ 00904 static VALUE 00905 path_world_writable_p(VALUE self) 00906 { 00907 return rb_funcall(rb_mFileTest, rb_intern("world_writable?"), 1, get_strpath(self)); 00908 } 00909 00910 /* 00911 * See FileTest.writable_real?. 00912 */ 00913 static VALUE 00914 path_writable_real_p(VALUE self) 00915 { 00916 return rb_funcall(rb_mFileTest, rb_intern("writable_real?"), 1, get_strpath(self)); 00917 } 00918 00919 /* 00920 * See FileTest.zero?. 00921 */ 00922 static VALUE 00923 path_zero_p(VALUE self) 00924 { 00925 return rb_funcall(rb_mFileTest, rb_intern("zero?"), 1, get_strpath(self)); 00926 } 00927 00928 static VALUE 00929 glob_i(VALUE elt, VALUE klass, int argc, VALUE *argv) 00930 { 00931 return rb_yield(rb_class_new_instance(1, &elt, klass)); 00932 } 00933 00934 /* 00935 * Returns or yields Pathname objects. 00936 * 00937 * Pathname.glob("config/" "*.rb") 00938 * #=> [#<Pathname:config/environment.rb>, #<Pathname:config/routes.rb>, ..] 00939 * 00940 * See Dir.glob. 00941 */ 00942 static VALUE 00943 path_s_glob(int argc, VALUE *argv, VALUE klass) 00944 { 00945 VALUE args[2]; 00946 int n; 00947 00948 n = rb_scan_args(argc, argv, "11", &args[0], &args[1]); 00949 if (rb_block_given_p()) { 00950 return rb_block_call(rb_cDir, rb_intern("glob"), n, args, glob_i, klass); 00951 } 00952 else { 00953 VALUE ary; 00954 long i; 00955 ary = rb_funcall2(rb_cDir, rb_intern("glob"), n, args); 00956 ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary"); 00957 for (i = 0; i < RARRAY_LEN(ary); i++) { 00958 VALUE elt = RARRAY_PTR(ary)[i]; 00959 elt = rb_class_new_instance(1, &elt, klass); 00960 rb_ary_store(ary, i, elt); 00961 } 00962 return ary; 00963 } 00964 } 00965 00966 /* 00967 * Returns the current working directory as a Pathname. 00968 * 00969 * Pathname.getwd 00970 * #=> #<Pathname:/home/zzak/projects/ruby> 00971 * 00972 * See Dir.getwd. 00973 */ 00974 static VALUE 00975 path_s_getwd(VALUE klass) 00976 { 00977 VALUE str; 00978 str = rb_funcall(rb_cDir, rb_intern("getwd"), 0); 00979 return rb_class_new_instance(1, &str, klass); 00980 } 00981 00982 /* 00983 * Return the entries (files and subdirectories) in the directory, each as a 00984 * Pathname object. 00985 * 00986 * The results contains just the names in the directory, without any trailing 00987 * slashes or recursive look-up. 00988 * 00989 * pp Pathname.new('/usr/local').entries 00990 * #=> [#<Pathname:share>, 00991 * # #<Pathname:lib>, 00992 * # #<Pathname:..>, 00993 * # #<Pathname:include>, 00994 * # #<Pathname:etc>, 00995 * # #<Pathname:bin>, 00996 * # #<Pathname:man>, 00997 * # #<Pathname:games>, 00998 * # #<Pathname:.>, 00999 * # #<Pathname:sbin>, 01000 * # #<Pathname:src>] 01001 * 01002 * The result may contain the current directory <code>#<Pathname:.></code> and 01003 * the parent directory <code>#<Pathname:..></code>. 01004 * 01005 * If you don't want +.+ and +..+ and 01006 * want directories, consider Pathname#children. 01007 */ 01008 static VALUE 01009 path_entries(VALUE self) 01010 { 01011 VALUE klass, str, ary; 01012 long i; 01013 klass = rb_obj_class(self); 01014 str = get_strpath(self); 01015 ary = rb_funcall(rb_cDir, rb_intern("entries"), 1, str); 01016 ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary"); 01017 for (i = 0; i < RARRAY_LEN(ary); i++) { 01018 VALUE elt = RARRAY_PTR(ary)[i]; 01019 elt = rb_class_new_instance(1, &elt, klass); 01020 rb_ary_store(ary, i, elt); 01021 } 01022 return ary; 01023 } 01024 01025 /* 01026 * Create the referenced directory. 01027 * 01028 * See Dir.mkdir. 01029 */ 01030 static VALUE 01031 path_mkdir(int argc, VALUE *argv, VALUE self) 01032 { 01033 VALUE str = get_strpath(self); 01034 VALUE vmode; 01035 if (rb_scan_args(argc, argv, "01", &vmode) == 0) 01036 return rb_funcall(rb_cDir, rb_intern("mkdir"), 1, str); 01037 else 01038 return rb_funcall(rb_cDir, rb_intern("mkdir"), 2, str, vmode); 01039 } 01040 01041 /* 01042 * Remove the referenced directory. 01043 * 01044 * See Dir.rmdir. 01045 */ 01046 static VALUE 01047 path_rmdir(VALUE self) 01048 { 01049 return rb_funcall(rb_cDir, rb_intern("rmdir"), 1, get_strpath(self)); 01050 } 01051 01052 /* 01053 * Opens the referenced directory. 01054 * 01055 * See Dir.open. 01056 */ 01057 static VALUE 01058 path_opendir(VALUE self) 01059 { 01060 VALUE args[1]; 01061 01062 args[0] = get_strpath(self); 01063 return rb_block_call(rb_cDir, rb_intern("open"), 1, args, 0, 0); 01064 } 01065 01066 static VALUE 01067 each_entry_i(VALUE elt, VALUE klass, int argc, VALUE *argv) 01068 { 01069 return rb_yield(rb_class_new_instance(1, &elt, klass)); 01070 } 01071 01072 /* 01073 * Iterates over the entries (files and subdirectories) in the directory, 01074 * yielding a Pathname object for each entry. 01075 */ 01076 static VALUE 01077 path_each_entry(VALUE self) 01078 { 01079 VALUE args[1]; 01080 01081 args[0] = get_strpath(self); 01082 return rb_block_call(rb_cDir, rb_intern("foreach"), 1, args, each_entry_i, rb_obj_class(self)); 01083 } 01084 01085 static VALUE 01086 unlink_body(VALUE str) 01087 { 01088 return rb_funcall(rb_cDir, rb_intern("unlink"), 1, str); 01089 } 01090 01091 static VALUE 01092 unlink_rescue(VALUE str, VALUE errinfo) 01093 { 01094 return rb_funcall(rb_cFile, rb_intern("unlink"), 1, str); 01095 } 01096 01097 /* 01098 * Removes a file or directory, using File.unlink if +self+ is a file, or 01099 * Dir.unlink as necessary. 01100 */ 01101 static VALUE 01102 path_unlink(VALUE self) 01103 { 01104 VALUE eENOTDIR = rb_const_get_at(rb_mErrno, rb_intern("ENOTDIR")); 01105 VALUE str = get_strpath(self); 01106 return rb_rescue2(unlink_body, str, unlink_rescue, str, eENOTDIR, (VALUE)0); 01107 } 01108 01109 /* 01110 * Creates a new Pathname object. 01111 */ 01112 static VALUE 01113 path_f_pathname(VALUE self, VALUE str) 01114 { 01115 return rb_class_new_instance(1, &str, rb_cPathname); 01116 } 01117 01118 /* 01119 * 01120 * Pathname represents the name of a file or directory on the filesystem, 01121 * but not the file itself. 01122 * 01123 * The pathname depends on the Operating System: Unix, Windows, etc. 01124 * This library works with pathnames of local OS, however non-Unix pathnames 01125 * are supported experimentally. 01126 * 01127 * A Pathname can be relative or absolute. It's not until you try to 01128 * reference the file that it even matters whether the file exists or not. 01129 * 01130 * Pathname is immutable. It has no method for destructive update. 01131 * 01132 * The goal of this class is to manipulate file path information in a neater 01133 * way than standard Ruby provides. The examples below demonstrate the 01134 * difference. 01135 * 01136 * *All* functionality from File, FileTest, and some from Dir and FileUtils is 01137 * included, in an unsurprising way. It is essentially a facade for all of 01138 * these, and more. 01139 * 01140 * == Examples 01141 * 01142 * === Example 1: Using Pathname 01143 * 01144 * require 'pathname' 01145 * pn = Pathname.new("/usr/bin/ruby") 01146 * size = pn.size # 27662 01147 * isdir = pn.directory? # false 01148 * dir = pn.dirname # Pathname:/usr/bin 01149 * base = pn.basename # Pathname:ruby 01150 * dir, base = pn.split # [Pathname:/usr/bin, Pathname:ruby] 01151 * data = pn.read 01152 * pn.open { |f| _ } 01153 * pn.each_line { |line| _ } 01154 * 01155 * === Example 2: Using standard Ruby 01156 * 01157 * pn = "/usr/bin/ruby" 01158 * size = File.size(pn) # 27662 01159 * isdir = File.directory?(pn) # false 01160 * dir = File.dirname(pn) # "/usr/bin" 01161 * base = File.basename(pn) # "ruby" 01162 * dir, base = File.split(pn) # ["/usr/bin", "ruby"] 01163 * data = File.read(pn) 01164 * File.open(pn) { |f| _ } 01165 * File.foreach(pn) { |line| _ } 01166 * 01167 * === Example 3: Special features 01168 * 01169 * p1 = Pathname.new("/usr/lib") # Pathname:/usr/lib 01170 * p2 = p1 + "ruby/1.8" # Pathname:/usr/lib/ruby/1.8 01171 * p3 = p1.parent # Pathname:/usr 01172 * p4 = p2.relative_path_from(p3) # Pathname:lib/ruby/1.8 01173 * pwd = Pathname.pwd # Pathname:/home/gavin 01174 * pwd.absolute? # true 01175 * p5 = Pathname.new "." # Pathname:. 01176 * p5 = p5 + "music/../articles" # Pathname:music/../articles 01177 * p5.cleanpath # Pathname:articles 01178 * p5.realpath # Pathname:/home/gavin/articles 01179 * p5.children # [Pathname:/home/gavin/articles/linux, ...] 01180 * 01181 * == Breakdown of functionality 01182 * 01183 * === Core methods 01184 * 01185 * These methods are effectively manipulating a String, because that's 01186 * all a path is. None of these access the file system except for 01187 * #mountpoint?, #children, #each_child, #realdirpath and #realpath. 01188 * 01189 * - + 01190 * - #join 01191 * - #parent 01192 * - #root? 01193 * - #absolute? 01194 * - #relative? 01195 * - #relative_path_from 01196 * - #each_filename 01197 * - #cleanpath 01198 * - #realpath 01199 * - #realdirpath 01200 * - #children 01201 * - #each_child 01202 * - #mountpoint? 01203 * 01204 * === File status predicate methods 01205 * 01206 * These methods are a facade for FileTest: 01207 * - #blockdev? 01208 * - #chardev? 01209 * - #directory? 01210 * - #executable? 01211 * - #executable_real? 01212 * - #exist? 01213 * - #file? 01214 * - #grpowned? 01215 * - #owned? 01216 * - #pipe? 01217 * - #readable? 01218 * - #world_readable? 01219 * - #readable_real? 01220 * - #setgid? 01221 * - #setuid? 01222 * - #size 01223 * - #size? 01224 * - #socket? 01225 * - #sticky? 01226 * - #symlink? 01227 * - #writable? 01228 * - #world_writable? 01229 * - #writable_real? 01230 * - #zero? 01231 * 01232 * === File property and manipulation methods 01233 * 01234 * These methods are a facade for File: 01235 * - #atime 01236 * - #ctime 01237 * - #mtime 01238 * - #chmod(mode) 01239 * - #lchmod(mode) 01240 * - #chown(owner, group) 01241 * - #lchown(owner, group) 01242 * - #fnmatch(pattern, *args) 01243 * - #fnmatch?(pattern, *args) 01244 * - #ftype 01245 * - #make_link(old) 01246 * - #open(*args, &block) 01247 * - #readlink 01248 * - #rename(to) 01249 * - #stat 01250 * - #lstat 01251 * - #make_symlink(old) 01252 * - #truncate(length) 01253 * - #utime(atime, mtime) 01254 * - #basename(*args) 01255 * - #dirname 01256 * - #extname 01257 * - #expand_path(*args) 01258 * - #split 01259 * 01260 * === Directory methods 01261 * 01262 * These methods are a facade for Dir: 01263 * - Pathname.glob(*args) 01264 * - Pathname.getwd / Pathname.pwd 01265 * - #rmdir 01266 * - #entries 01267 * - #each_entry(&block) 01268 * - #mkdir(*args) 01269 * - #opendir(*args) 01270 * 01271 * === IO 01272 * 01273 * These methods are a facade for IO: 01274 * - #each_line(*args, &block) 01275 * - #read(*args) 01276 * - #binread(*args) 01277 * - #readlines(*args) 01278 * - #sysopen(*args) 01279 * 01280 * === Utilities 01281 * 01282 * These methods are a mixture of Find, FileUtils, and others: 01283 * - #find(&block) 01284 * - #mkpath 01285 * - #rmtree 01286 * - #unlink / #delete 01287 * 01288 * 01289 * == Method documentation 01290 * 01291 * As the above section shows, most of the methods in Pathname are facades. The 01292 * documentation for these methods generally just says, for instance, "See 01293 * FileTest.writable?", as you should be familiar with the original method 01294 * anyway, and its documentation (e.g. through +ri+) will contain more 01295 * information. In some cases, a brief description will follow. 01296 */ 01297 void 01298 Init_pathname() 01299 { 01300 id_at_path = rb_intern("@path"); 01301 id_to_path = rb_intern("to_path"); 01302 01303 rb_cPathname = rb_define_class("Pathname", rb_cObject); 01304 rb_define_method(rb_cPathname, "initialize", path_initialize, 1); 01305 rb_define_method(rb_cPathname, "freeze", path_freeze, 0); 01306 rb_define_method(rb_cPathname, "taint", path_taint, 0); 01307 rb_define_method(rb_cPathname, "untaint", path_untaint, 0); 01308 rb_define_method(rb_cPathname, "==", path_eq, 1); 01309 rb_define_method(rb_cPathname, "===", path_eq, 1); 01310 rb_define_method(rb_cPathname, "eql?", path_eq, 1); 01311 rb_define_method(rb_cPathname, "<=>", path_cmp, 1); 01312 rb_define_method(rb_cPathname, "hash", path_hash, 0); 01313 rb_define_method(rb_cPathname, "to_s", path_to_s, 0); 01314 rb_define_method(rb_cPathname, "to_path", path_to_s, 0); 01315 rb_define_method(rb_cPathname, "inspect", path_inspect, 0); 01316 rb_define_method(rb_cPathname, "sub", path_sub, -1); 01317 rb_define_method(rb_cPathname, "sub_ext", path_sub_ext, 1); 01318 rb_define_method(rb_cPathname, "realpath", path_realpath, -1); 01319 rb_define_method(rb_cPathname, "realdirpath", path_realdirpath, -1); 01320 rb_define_method(rb_cPathname, "each_line", path_each_line, -1); 01321 rb_define_method(rb_cPathname, "read", path_read, -1); 01322 rb_define_method(rb_cPathname, "binread", path_binread, -1); 01323 rb_define_method(rb_cPathname, "readlines", path_readlines, -1); 01324 rb_define_method(rb_cPathname, "sysopen", path_sysopen, -1); 01325 rb_define_method(rb_cPathname, "atime", path_atime, 0); 01326 rb_define_method(rb_cPathname, "ctime", path_ctime, 0); 01327 rb_define_method(rb_cPathname, "mtime", path_mtime, 0); 01328 rb_define_method(rb_cPathname, "chmod", path_chmod, 1); 01329 rb_define_method(rb_cPathname, "lchmod", path_lchmod, 1); 01330 rb_define_method(rb_cPathname, "chown", path_chown, 2); 01331 rb_define_method(rb_cPathname, "lchown", path_lchown, 2); 01332 rb_define_method(rb_cPathname, "fnmatch", path_fnmatch, -1); 01333 rb_define_method(rb_cPathname, "fnmatch?", path_fnmatch, -1); 01334 rb_define_method(rb_cPathname, "ftype", path_ftype, 0); 01335 rb_define_method(rb_cPathname, "make_link", path_make_link, 1); 01336 rb_define_method(rb_cPathname, "open", path_open, -1); 01337 rb_define_method(rb_cPathname, "readlink", path_readlink, 0); 01338 rb_define_method(rb_cPathname, "rename", path_rename, 1); 01339 rb_define_method(rb_cPathname, "stat", path_stat, 0); 01340 rb_define_method(rb_cPathname, "lstat", path_lstat, 0); 01341 rb_define_method(rb_cPathname, "make_symlink", path_make_symlink, 1); 01342 rb_define_method(rb_cPathname, "truncate", path_truncate, 1); 01343 rb_define_method(rb_cPathname, "utime", path_utime, 2); 01344 rb_define_method(rb_cPathname, "basename", path_basename, -1); 01345 rb_define_method(rb_cPathname, "dirname", path_dirname, 0); 01346 rb_define_method(rb_cPathname, "extname", path_extname, 0); 01347 rb_define_method(rb_cPathname, "expand_path", path_expand_path, -1); 01348 rb_define_method(rb_cPathname, "split", path_split, 0); 01349 rb_define_method(rb_cPathname, "blockdev?", path_blockdev_p, 0); 01350 rb_define_method(rb_cPathname, "chardev?", path_chardev_p, 0); 01351 rb_define_method(rb_cPathname, "executable?", path_executable_p, 0); 01352 rb_define_method(rb_cPathname, "executable_real?", path_executable_real_p, 0); 01353 rb_define_method(rb_cPathname, "exist?", path_exist_p, 0); 01354 rb_define_method(rb_cPathname, "grpowned?", path_grpowned_p, 0); 01355 rb_define_method(rb_cPathname, "directory?", path_directory_p, 0); 01356 rb_define_method(rb_cPathname, "file?", path_file_p, 0); 01357 rb_define_method(rb_cPathname, "pipe?", path_pipe_p, 0); 01358 rb_define_method(rb_cPathname, "socket?", path_socket_p, 0); 01359 rb_define_method(rb_cPathname, "owned?", path_owned_p, 0); 01360 rb_define_method(rb_cPathname, "readable?", path_readable_p, 0); 01361 rb_define_method(rb_cPathname, "world_readable?", path_world_readable_p, 0); 01362 rb_define_method(rb_cPathname, "readable_real?", path_readable_real_p, 0); 01363 rb_define_method(rb_cPathname, "setuid?", path_setuid_p, 0); 01364 rb_define_method(rb_cPathname, "setgid?", path_setgid_p, 0); 01365 rb_define_method(rb_cPathname, "size", path_size, 0); 01366 rb_define_method(rb_cPathname, "size?", path_size_p, 0); 01367 rb_define_method(rb_cPathname, "sticky?", path_sticky_p, 0); 01368 rb_define_method(rb_cPathname, "symlink?", path_symlink_p, 0); 01369 rb_define_method(rb_cPathname, "writable?", path_writable_p, 0); 01370 rb_define_method(rb_cPathname, "world_writable?", path_world_writable_p, 0); 01371 rb_define_method(rb_cPathname, "writable_real?", path_writable_real_p, 0); 01372 rb_define_method(rb_cPathname, "zero?", path_zero_p, 0); 01373 rb_define_singleton_method(rb_cPathname, "glob", path_s_glob, -1); 01374 rb_define_singleton_method(rb_cPathname, "getwd", path_s_getwd, 0); 01375 rb_define_singleton_method(rb_cPathname, "pwd", path_s_getwd, 0); 01376 rb_define_method(rb_cPathname, "entries", path_entries, 0); 01377 rb_define_method(rb_cPathname, "mkdir", path_mkdir, -1); 01378 rb_define_method(rb_cPathname, "rmdir", path_rmdir, 0); 01379 rb_define_method(rb_cPathname, "opendir", path_opendir, 0); 01380 rb_define_method(rb_cPathname, "each_entry", path_each_entry, 0); 01381 rb_define_method(rb_cPathname, "unlink", path_unlink, 0); 01382 rb_define_method(rb_cPathname, "delete", path_unlink, 0); 01383 rb_undef_method(rb_cPathname, "=~"); 01384 rb_define_global_function("Pathname", path_f_pathname, 1); 01385 } 01386