/* * call-seq: * File.identical?(file_1, file_2) => true or false * * Returns <code>true</code> if the named files are identical. * * open("a", "w") {} * p File.identical?("a", "a") #=> true * p File.identical?("a", "./a") #=> true * File.link("a", "b") * p File.identical?("a", "b") #=> true * File.symlink("a", "c") * p File.identical?("a", "c") #=> true * open("d", "w") {} * p File.identical?("a", "d") #=> false */ static VALUE test_identical(obj, fname1, fname2) VALUE obj, fname1, fname2; { #ifndef DOSISH struct stat st1, st2; if (rb_stat(fname1, &st1) < 0) return Qfalse; if (rb_stat(fname2, &st2) < 0) return Qfalse; if (st1.st_dev != st2.st_dev) return Qfalse; if (st1.st_ino != st2.st_ino) return Qfalse; #else #ifdef _WIN32 BY_HANDLE_FILE_INFORMATION st1, st2; HANDLE f1 = 0, f2 = 0; #endif rb_secure(2); #ifdef _WIN32 f1 = w32_io_info(&fname1, &st1); if (f1 == INVALID_HANDLE_VALUE) return Qfalse; f2 = w32_io_info(&fname2, &st2); if (f1) CloseHandle(f1); if (f2 == INVALID_HANDLE_VALUE) return Qfalse; if (f2) CloseHandle(f2); if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber && st1.nFileIndexHigh == st2.nFileIndexHigh && st1.nFileIndexLow == st2.nFileIndexLow) return Qtrue; if (!f1 || !f2) return Qfalse; if (rb_w32_iswin95()) return Qfalse; #else SafeStringValue(fname1); fname1 = rb_str_new4(fname1); SafeStringValue(fname2); if (access(RSTRING(fname1)->ptr, 0)) return Qfalse; if (access(RSTRING(fname2)->ptr, 0)) return Qfalse; #endif fname1 = rb_file_expand_path(fname1, Qnil); fname2 = rb_file_expand_path(fname2, Qnil); if (RSTRING(fname1)->len != RSTRING(fname2)->len) return Qfalse; if (rb_memcicmp(RSTRING(fname1)->ptr, RSTRING(fname2)->ptr, RSTRING(fname1)->len)) return Qfalse; #endif return Qtrue; }