diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-11-22 16:26:39 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-11-22 16:26:39 +0000 |
commit | b7259a7a3b52aede7dc946fcf295c36d01fcb52a (patch) | |
tree | 627508398d5732f322df2321749b2dd10cd9f55e | |
parent | 1670586349ea030907464248d63875ecbe5a105f (diff) | |
download | ruby-b7259a7a3b52aede7dc946fcf295c36d01fcb52a.tar.gz ruby-b7259a7a3b52aede7dc946fcf295c36d01fcb52a.tar.xz ruby-b7259a7a3b52aede7dc946fcf295c36d01fcb52a.zip |
* file.c (test_identical): test if two files are identical.
* file.c (rb_f_test): support DOSISH systems where st_ino is not
reliable. fixed: [ruby-core:06672]
* win32.h, win32.c (rb_w32_osid): check the running platform.
git-svn-id: http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8@9590 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | file.c | 103 | ||||
-rw-r--r-- | win32/win32.c | 28 | ||||
-rw-r--r-- | win32/win32.h | 15 |
4 files changed, 124 insertions, 31 deletions
@@ -1,3 +1,12 @@ +Wed Nov 23 01:22:57 2005 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * file.c (test_identical): test if two files are identical. + + * file.c (rb_f_test): support DOSISH systems where st_ino is not + reliable. fixed: [ruby-core:06672] + + * win32.h, win32.c (rb_w32_osid): check the running platform. + Tue Nov 22 23:52:06 2005 Nobuyoshi Nakada <nobu@ruby-lang.org> * lib/optparse.rb: match incomplete (in current enconding) multibyte @@ -662,6 +662,34 @@ rb_stat(file, st) return stat(StringValueCStr(file), st); } +#ifdef _WIN32 +static HANDLE +w32_io_info(file, st) + 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: * File.stat(file_name) => stat @@ -1309,7 +1337,7 @@ check3rdbyte(fname, mode) * call-seq: * File.setuid?(file_name) => true or false * - * Returns <code>true</code> if the named file is a has the setuid bit set. + * Returns <code>true</code> if the named file has the setuid bit set. */ static VALUE @@ -1327,7 +1355,7 @@ test_suid(obj, fname) * call-seq: * File.setgid?(file_name) => true or false * - * Returns <code>true</code> if the named file is a has the setgid bit set. + * Returns <code>true</code> if the named file has the setgid bit set. */ static VALUE @@ -1345,7 +1373,7 @@ test_sgid(obj, fname) * call-seq: * File.sticky?(file_name) => true or false * - * Returns <code>true</code> if the named file is a has the sticky bit set. + * Returns <code>true</code> if the named file has the sticky bit set. */ static VALUE @@ -1361,6 +1389,61 @@ test_sticky(obj, fname) /* * call-seq: + * File.identical?(file_1, file_2) => true or false + * + * Returns <code>true</code> if the named files are identical. + */ + +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 + FilePathValue(fname1); + fname1 = rb_str_new4(fname1); + FilePathValue(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; +} + +/* + * call-seq: * File.size(file_name) => integer * * Returns the size of <code>file_name</code>. @@ -3290,7 +3373,12 @@ rb_f_test(argc, argv) } } - if (strchr("-=<>", cmd)) { + if (cmd == '-') { + CHECK(2); + return test_identical(0, argv[1], argv[2]); + } + + if (strchr("=<>", cmd)) { struct stat st1, st2; CHECK(2); @@ -3298,11 +3386,6 @@ rb_f_test(argc, argv) if (rb_stat(argv[2], &st2) < 0) return Qfalse; 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; return Qfalse; @@ -4262,6 +4345,8 @@ Init_File() define_filetest_function("setgid?", test_sgid, 1); 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); rb_define_singleton_method(rb_cFile, "ftype", rb_file_s_ftype, 1); diff --git a/win32/win32.c b/win32/win32.c index 5ec3aea4a..530cada51 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -47,12 +47,6 @@ #define bool int #endif -#ifdef _M_IX86 -# define WIN95 1 -#else -# undef WIN95 -#endif - #if defined __BORLANDC__ || defined _WIN32_WCE # define _filbuf _fgetc # define _flsbuf _fputc @@ -209,10 +203,10 @@ map_errno(DWORD winerr) static char *NTLoginName; #ifdef WIN95 -DWORD Win32System = (DWORD)-1; +static DWORD Win32System = (DWORD)-1; -static DWORD -IdOS(void) +DWORD +rb_w32_osid(void) { static OSVERSIONINFO osver; @@ -224,21 +218,11 @@ IdOS(void) } return (Win32System); } - -static int -IsWin95(void) { - return (IdOS() == VER_PLATFORM_WIN32_WINDOWS); -} - -static int -IsWinNT(void) { - return (IdOS() == VER_PLATFORM_WIN32_NT); -} -#else -# define IsWinNT() TRUE -# define IsWin95() FALSE #endif +#define IsWinNT() rb_w32_iswinnt() +#define IsWin95() rb_w32_iswin95() + /* main thread constants */ static struct { HANDLE handle; diff --git a/win32/win32.h b/win32/win32.h index 5a93f2d31..2d88de472 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -74,6 +74,21 @@ extern "C++" { } #endif +#ifdef _M_IX86 +# define WIN95 1 +#else +# undef WIN95 +#endif + +#ifdef WIN95 +extern DWORD rb_w32_osid(void); +#define rb_w32_iswinnt() (rb_w32_osid() == VER_PLATFORM_WIN32_NT) +#define rb_w32_iswin95() (rb_w32_osid() == VER_PLATFORM_WIN32_WINDOWS) +#else +#define rb_w32_iswinnt() TRUE +#define rb_w32_iswin95() FALSE +#endif + #define WNOHANG -1 #undef getc |