Hi,

At Tue, 22 Nov 2005 07:39:01 +0900,
daz wrote in [ruby-core:06683]:
> If there aren't any hard links on Win9X, all I can
> think of is to compare the same file:

AFAIK, Win9X family don't support NTFS and others, which is
required for hard links and reparse points.  The only way I
thought of is to compare expanded pathes.

> I'm not asking questions, just sending feedback as I'm
> the last person on the planet using 9X ;))

An `endangered species'?


Index: file.c =================================================================== RCS file: /cvs/ruby/src/ruby/file.c,v retrieving revision 1.227 diff -U2 -p -u -r1.227 file.c --- file.c 21 Nov 2005 16:47:06 -0000 1.227 +++ file.c 22 Nov 2005 04:00:21 -0000 @@ -637,4 +637,30 @@ 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; + + 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 +1389,51 @@ test_sticky(VALUE obj, VALUE fname) } +static VALUE +test_identical(VALUE obj, VALUE fname1, VALUE 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_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 && + st1.nFileIndexHigh == st2.nFileIndexHigh && + st1.nFileIndexLow == st2.nFileIndexLow) + return Qtrue; + if (!f1 || !f2) return Qfalse; + /* only Win9X? */ +#else + FilePathValue(file1); + file1 = rb_str_new4(file1); + FilePathValue(file2); + if (access(RSTRING(file1)->ptr, 0)) return Qfalse; + if (access(RSTRING(file2)->ptr, 0)) return Qfalse; +#endif + file1 = rb_file_expand_path(file1, Qnil); + file2 = rb_file_expand_path(file2, Qnil); + if (RSTRING(file1)->len != RSTRING(file2)->len) return Qfalse; + if (rb_memcicmp(RSTRING(file1)->ptr, RSTRING(file2)->ptr, RSTRING(file1)->len)) + return Qfalse; +#endif + return Qtrue; +} + /* * call-seq: @@ -3220,5 +3293,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; @@ -3228,9 +3306,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; @@ -4199,4 +4272,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