summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-11-22 16:26:39 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-11-22 16:26:39 +0000
commitb7259a7a3b52aede7dc946fcf295c36d01fcb52a (patch)
tree627508398d5732f322df2321749b2dd10cd9f55e
parent1670586349ea030907464248d63875ecbe5a105f (diff)
downloadruby-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--ChangeLog9
-rw-r--r--file.c103
-rw-r--r--win32/win32.c28
-rw-r--r--win32/win32.h15
4 files changed, 124 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index 270cb82fa..6b26682c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/file.c b/file.c
index 25d516606..3969d85ad 100644
--- a/file.c
+++ b/file.c
@@ -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