Hi,

At Mon, 21 Nov 2005 01:44:34 +0900,
noreply / rubyforge.org wrote in [ruby-core:06672]:
> Tested on Windows XP, NTFS, Ruby 1.8.2 (OneClick Installer):
> 
>   $ ri test
> 
> states:
> 
>   "?-  | boolean | True if file1 is a hard link to file2"
> 
> On the specified platform
> 
>   test(?-, "file1", "file2")
> 
> returns true for any "file1" and "file2" that exist, not only
> for hardlinks. It works as expected on my Linux system.

I'm not sure if this works on Win9X or not.


Index: file.c =================================================================== RCS file: /cvs/ruby/src/ruby/file.c,v retrieving revision 1.225 diff -U2 -p -r1.225 file.c --- file.c 18 Nov 2005 09:09:23 -0000 1.225 +++ file.c 21 Nov 2005 01:41:41 -0000 @@ -637,4 +637,31 @@ rb_stat(VALUE file, struct stat *st) } +#ifdef _WIN32 +static HANDLE +w32_stat(VALUE file, BY_HANDLE_FILE_INFORMATION *st) +{ + VALUE tmp; + HANDLE f, ret = 0; + + rb_secure(2); + tmp = rb_check_convert_type(file, T_FILE, "IO", "to_io"); + if (!NIL_P(tmp)) { + OpenFile *fptr; + + GetOpenFile(tmp, fptr); + f = (HANDLE)rb_w32_get_osfhandle(fptr->fd); + } + else { + FilePathValue(file); + f = CreateFile(StringValueCStr(file), 0, 0, NULL, + OPEN_EXISTING, 0, NULL); + if (f == INVALID_HANDLE_VALUE) return f; + ret = f; + } + if (GetFileInformationByHandle(f, st)) return ret; + return INVALID_HANDLE_VALUE; +} +#endif + /* * call-seq: @@ -1363,4 +1390,33 @@ test_sticky(VALUE obj, VALUE fname) } +static VALUE +test_identical(VALUE obj, VALUE fname1, VALUE fname2) +{ +#ifndef _WIN32 + 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 + BY_HANDLE_FILE_INFORMATION st1, st2; + HANDLE f1 = 0, f2 = 0; + VALUE tmp; + + f1 = w32_stat(fname1, &st1); + if (f1 == INVALID_HANDLE_VALUE) return Qfalse; + f2 = w32_stat(fname2, &st2); + if (f1) CloseHandle(f1); + if (f2 == INVALID_HANDLE_VALUE) return Qfalse; + if (f2) CloseHandle(f2); + + if (st1.dwVolumeSerialNumber != st2.dwVolumeSerialNumber) return Qfalse; + if (st1.nFileIndexHigh != st2.nFileIndexHigh) return Qfalse; + if (st1.nFileIndexLow != st2.nFileIndexLow) return Qfalse; +#endif + return Qtrue; +} + /* * call-seq: @@ -3197,5 +3253,10 @@ rb_f_test(int argc, VALUE *argv) } - if (strchr("-=<>", cmd)) { + if (cmd == '-') { + CHECK(2); + return test_identical(0, argv[1], argv[2]); + } + + if (strchr("=<>", cmd)) { struct stat st1, st2; @@ -3205,9 +3266,4 @@ rb_f_test(int argc, VALUE *argv) switch (cmd) { - case '-': - if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) - return Qtrue; - return Qfalse; - case '=': if (st1.st_mtime == st2.st_mtime) return Qtrue; @@ -4176,4 +4232,6 @@ Init_File(void) define_filetest_function("sticky?", test_sticky, 1); + define_filetest_function("identical?", test_identical, 2); + rb_define_singleton_method(rb_cFile, "stat", rb_file_s_stat, 1); rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1);
-- Nobu Nakada