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