Commit dd754220 authored by takahashim's avatar takahashim

Fix for windows(mingw)

* File.expand_path: support drive letter and ALT_SEPARATOR

* File.dirname: support ALT_SEPARATOR
* File.basename: ditto.

* IO.popen: raise NotImplementedError
* IO.pipe: ditto.
* `cmd`:  ditto.
* File#flock: ditto.
* FileTest.pipe?: ditto.
* FileTest.symlink?: ditto.
* FileTest.socket?: ditto.
parent 68de1e4f
...@@ -89,14 +89,21 @@ class File < IO ...@@ -89,14 +89,21 @@ class File < IO
end end
expanded_path = concat_path(path, default_dir) expanded_path = concat_path(path, default_dir)
drive_prefix = ""
if File::ALT_SEPARATOR && expanded_path.size > 2 &&
("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":"
drive_prefix = expanded_path[0, 2]
expanded_path = expanded_path[2, expanded_path.size]
end
expand_path_array = [] expand_path_array = []
if File::ALT_SEPARATOR && expanded_path.include?(File::ALT_SEPARATOR)
expanded_path.gsub!(File::ALT_SEPARATOR, '/')
end
while expanded_path.include?('//') while expanded_path.include?('//')
expanded_path = expanded_path.gsub('//', '/') expanded_path = expanded_path.gsub('//', '/')
end end
if expanded_path == "/" if expanded_path != "/"
expanded_path
else
expanded_path.split('/').each do |path_token| expanded_path.split('/').each do |path_token|
if path_token == '..' if path_token == '..'
if expand_path_array.size > 1 if expand_path_array.size > 1
...@@ -109,8 +116,15 @@ class File < IO ...@@ -109,8 +116,15 @@ class File < IO
end end
end end
expand_path = expand_path_array.join("/") expanded_path = expand_path_array.join("/")
expand_path.empty? ? '/' : expand_path if expanded_path.empty?
expanded_path = '/'
end
end
if drive_prefix.empty?
expanded_path
else
drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR)
end end
end end
......
...@@ -27,6 +27,9 @@ class IO ...@@ -27,6 +27,9 @@ class IO
end end
def self.popen(command, mode = 'r', &block) def self.popen(command, mode = 'r', &block)
if !self.respond_to?(:_popen)
raise NotImplementedError, "popen is not supported on this platform"
end
io = self._popen(command, mode) io = self._popen(command, mode)
return io unless block return io unless block
...@@ -42,6 +45,9 @@ class IO ...@@ -42,6 +45,9 @@ class IO
end end
def self.pipe(&block) def self.pipe(&block)
if !self.respond_to?(:_pipe)
raise NotImplementedError, "pipe is not supported on this platform"
end
if block if block
begin begin
r, w = IO._pipe r, w = IO._pipe
......
...@@ -130,17 +130,28 @@ mrb_file_s_rename(mrb_state *mrb, mrb_value obj) ...@@ -130,17 +130,28 @@ mrb_file_s_rename(mrb_state *mrb, mrb_value obj)
static mrb_value static mrb_value
mrb_file_dirname(mrb_state *mrb, mrb_value klass) mrb_file_dirname(mrb_state *mrb, mrb_value klass)
{ {
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
char dname[_MAX_DIR], vname[_MAX_DRIVE]; char dname[_MAX_DIR], vname[_MAX_DRIVE];
char buffer[_MAX_DRIVE + _MAX_DIR]; char buffer[_MAX_DRIVE + _MAX_DIR];
char *path; char *path;
size_t ridx;
mrb_value s; mrb_value s;
mrb_get_args(mrb, "S", &s); mrb_get_args(mrb, "S", &s);
path = mrb_str_to_cstr(mrb, s); path = mrb_str_to_cstr(mrb, s);
_splitpath((const char*)path, vname, dname, NULL, NULL); _splitpath((const char*)path, vname, dname, NULL, NULL);
snprintf(buffer, _MAX_DRIVE + _MAX_DIR, "%s%s", vname, dname); snprintf(buffer, _MAX_DRIVE + _MAX_DIR, "%s%s", vname, dname);
ridx = strlen(buffer);
if (ridx == 0) {
strncpy(buffer, ".", 2); /* null terminated */
} else if (ridx > 1) {
ridx--;
while (ridx > 0 && (buffer[ridx] == '/' || buffer[ridx] == '\\')) {
buffer[ridx] = '\0'; /* remove last char */
ridx--;
}
}
return mrb_str_new_cstr(mrb, buffer); return mrb_str_new_cstr(mrb, buffer);
#else #else
char *dname, *path; char *dname, *path;
mrb_value s; mrb_value s;
mrb_get_args(mrb, "S", &s); mrb_get_args(mrb, "S", &s);
...@@ -149,25 +160,37 @@ mrb_file_dirname(mrb_state *mrb, mrb_value klass) ...@@ -149,25 +160,37 @@ mrb_file_dirname(mrb_state *mrb, mrb_value klass)
if ((dname = dirname(path)) == NULL) { if ((dname = dirname(path)) == NULL) {
mrb_sys_fail(mrb, "dirname"); mrb_sys_fail(mrb, "dirname");
} }
#endif #endif
return mrb_str_new_cstr(mrb, dname); return mrb_str_new_cstr(mrb, dname);
} }
static mrb_value static mrb_value
mrb_file_basename(mrb_state *mrb, mrb_value klass) mrb_file_basename(mrb_state *mrb, mrb_value klass)
{ {
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
char bname[_MAX_DIR]; char bname[_MAX_DIR];
char extname[_MAX_EXT]; char extname[_MAX_EXT];
char *path; char *path;
size_t ridx;
char buffer[_MAX_DIR + _MAX_EXT]; char buffer[_MAX_DIR + _MAX_EXT];
mrb_value s; mrb_value s;
mrb_get_args(mrb, "S", &s); mrb_get_args(mrb, "S", &s);
path = mrb_str_to_cstr(mrb, s); path = mrb_str_to_cstr(mrb, s);
ridx = strlen(path);
if (ridx > 0) {
ridx--;
while (ridx > 0 && (path[ridx] == '/' || path[ridx] == '\\')) {
path[ridx] = '\0';
ridx--;
}
if (strncmp(path, "/", 2) == 0) {
return mrb_str_new_cstr(mrb, path);
}
}
_splitpath((const char*)path, NULL, NULL, bname, extname); _splitpath((const char*)path, NULL, NULL, bname, extname);
snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname); snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname);
return mrb_str_new_cstr(mrb, buffer); return mrb_str_new_cstr(mrb, buffer);
#else #else
char *bname, *path; char *bname, *path;
mrb_value s; mrb_value s;
mrb_get_args(mrb, "S", &s); mrb_get_args(mrb, "S", &s);
...@@ -176,7 +199,7 @@ mrb_file_basename(mrb_state *mrb, mrb_value klass) ...@@ -176,7 +199,7 @@ mrb_file_basename(mrb_state *mrb, mrb_value klass)
mrb_sys_fail(mrb, "basename"); mrb_sys_fail(mrb, "basename");
} }
return mrb_str_new_cstr(mrb, bname); return mrb_str_new_cstr(mrb, bname);
#endif #endif
} }
static mrb_value static mrb_value
...@@ -255,12 +278,11 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass) ...@@ -255,12 +278,11 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass)
#endif #endif
} }
#ifndef _WIN32
mrb_value mrb_value
mrb_file_flock(mrb_state *mrb, mrb_value self) mrb_file_flock(mrb_state *mrb, mrb_value self)
{ {
#if defined(sun) #if defined(_WIN32) || defined(_WIN64) || defined(sun)
mrb_raise(mrb, E_RUNTIME_ERROR, "flock is not supported on Illumos/Solaris"); mrb_raise(mrb, E_NOTIMP_ERROR, "flock is not supported on Illumos/Solaris/Windows");
#else #else
mrb_int operation; mrb_int operation;
int fd; int fd;
...@@ -289,7 +311,6 @@ mrb_file_flock(mrb_state *mrb, mrb_value self) ...@@ -289,7 +311,6 @@ mrb_file_flock(mrb_state *mrb, mrb_value self)
#endif #endif
return mrb_fixnum_value(0); return mrb_fixnum_value(0);
} }
#endif
static mrb_value static mrb_value
mrb_file_s_symlink(mrb_state *mrb, mrb_value klass) mrb_file_s_symlink(mrb_state *mrb, mrb_value klass)
...@@ -333,9 +354,7 @@ mrb_init_file(mrb_state *mrb) ...@@ -333,9 +354,7 @@ mrb_init_file(mrb_state *mrb)
mrb_define_class_method(mrb, file, "_getwd", mrb_file__getwd, MRB_ARGS_NONE()); mrb_define_class_method(mrb, file, "_getwd", mrb_file__getwd, MRB_ARGS_NONE());
mrb_define_class_method(mrb, file, "_gethome", mrb_file__gethome, MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, file, "_gethome", mrb_file__gethome, MRB_ARGS_OPT(1));
#ifndef _WIN32
mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1)); mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1));
#endif
cnst = mrb_define_module_under(mrb, file, "Constants"); cnst = mrb_define_module_under(mrb, file, "Constants");
mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH)); mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH));
......
...@@ -128,6 +128,9 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass) ...@@ -128,6 +128,9 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
mrb_value mrb_value
mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass) mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
{ {
#if defined(_WIN32) || defined(_WIN64)
mrb_raise(mrb, E_NOTIMP_ERROR, "pipe is not supported on this platform");
#else
#ifdef S_IFIFO #ifdef S_IFIFO
# ifndef S_ISFIFO # ifndef S_ISFIFO
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
...@@ -145,6 +148,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass) ...@@ -145,6 +148,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
#endif #endif
return mrb_false_value(); return mrb_false_value();
#endif
} }
/* /*
...@@ -157,6 +161,9 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass) ...@@ -157,6 +161,9 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
mrb_value mrb_value
mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass) mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
{ {
#if defined(_WIN32) || defined(_WIN64)
mrb_raise(mrb, E_NOTIMP_ERROR, "symlink is not supported on this platform");
#else
#ifndef S_ISLNK #ifndef S_ISLNK
# ifdef _S_ISLNK # ifdef _S_ISLNK
# define S_ISLNK(m) _S_ISLNK(m) # define S_ISLNK(m) _S_ISLNK(m)
...@@ -184,6 +191,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass) ...@@ -184,6 +191,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
#endif #endif
return mrb_false_value(); return mrb_false_value();
#endif
} }
/* /*
...@@ -196,6 +204,9 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass) ...@@ -196,6 +204,9 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
mrb_value mrb_value
mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass) mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
{ {
#if defined(_WIN32) || defined(_WIN64)
mrb_raise(mrb, E_NOTIMP_ERROR, "socket is not supported on this platform");
#else
#ifndef S_ISSOCK #ifndef S_ISSOCK
# ifdef _S_ISSOCK # ifdef _S_ISSOCK
# define S_ISSOCK(m) _S_ISSOCK(m) # define S_ISSOCK(m) _S_ISSOCK(m)
...@@ -223,6 +234,7 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass) ...@@ -223,6 +234,7 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
#endif #endif
return mrb_false_value(); return mrb_false_value();
#endif
} }
/* /*
......
...@@ -56,12 +56,16 @@ end ...@@ -56,12 +56,16 @@ end
assert('IO#flock') do assert('IO#flock') do
f = File.open $mrbtest_io_rfname f = File.open $mrbtest_io_rfname
begin
assert_equal(f.flock(File::LOCK_SH), 0) assert_equal(f.flock(File::LOCK_SH), 0)
assert_equal(f.flock(File::LOCK_UN), 0) assert_equal(f.flock(File::LOCK_UN), 0)
assert_equal(f.flock(File::LOCK_EX | File::LOCK_NB), 0) assert_equal(f.flock(File::LOCK_EX | File::LOCK_NB), 0)
assert_equal(f.flock(File::LOCK_UN), 0) assert_equal(f.flock(File::LOCK_UN), 0)
rescue NotImplementedError => e
skip e.message
ensure
f.close f.close
true end
end end
assert('File.join') do assert('File.join') do
...@@ -76,8 +80,13 @@ assert('File.join') do ...@@ -76,8 +80,13 @@ assert('File.join') do
end end
assert('File.realpath') do assert('File.realpath') do
if File.const_defined?(:ALT_SEPARATOR) && File::ALT_SEPARATOR
readme_path = File._getwd + File::ALT_SEPARATOR + "README.md"
assert_equal readme_path, File.realpath("README.md")
else
usrbin = IO.popen("cd bin; /bin/pwd -P") { |f| f.read.chomp } usrbin = IO.popen("cd bin; /bin/pwd -P") { |f| f.read.chomp }
assert_equal usrbin, File.realpath("bin") assert_equal usrbin, File.realpath("bin")
end
end end
assert('File TEST CLEANUP') do assert('File TEST CLEANUP') do
...@@ -95,7 +104,12 @@ assert('File.expand_path') do ...@@ -95,7 +104,12 @@ assert('File.expand_path') do
assert_equal "/hoge", File.expand_path("////tmp/..///////hoge") assert_equal "/hoge", File.expand_path("////tmp/..///////hoge")
assert_equal "/", File.expand_path("../../../..", "/") assert_equal "/", File.expand_path("../../../..", "/")
if File._getwd[1] == ":"
drive_letter = File._getwd[0]
assert_equal drive_letter + ":\\", File.expand_path(([".."] * 100).join("/"))
else
assert_equal "/", File.expand_path(([".."] * 100).join("/")) assert_equal "/", File.expand_path(([".."] * 100).join("/"))
end
end end
assert('File.expand_path (with ENV)') do assert('File.expand_path (with ENV)') do
......
...@@ -6,8 +6,8 @@ assert('FileTest TEST SETUP') do ...@@ -6,8 +6,8 @@ assert('FileTest TEST SETUP') do
end end
assert("FileTest.directory?") do assert("FileTest.directory?") do
assert_equal true, FileTest.directory?("/tmp") assert_equal true, FileTest.directory?(File.join(File._getwd, "mrblib"))
assert_equal false, FileTest.directory?("/bin/sh") assert_equal false, FileTest.directory?(File.join(File._getwd, "README.md"))
end end
assert("FileTest.exist?") do assert("FileTest.exist?") do
...@@ -23,14 +23,18 @@ assert("FileTest.exist?") do ...@@ -23,14 +23,18 @@ assert("FileTest.exist?") do
end end
assert("FileTest.file?") do assert("FileTest.file?") do
assert_equal false, FileTest.file?("/tmp") assert_equal false, FileTest.file?(File.join(File._getwd, "mrblib"))
assert_equal true, FileTest.file?("/bin/sh") assert_equal true, FileTest.file?(File.join(File._getwd, "README.md"))
end end
assert("FileTest.pipe?") do assert("FileTest.pipe?") do
begin
assert_equal false, FileTest.pipe?("/tmp")
io = IO.popen("ls") io = IO.popen("ls")
assert_equal true, FileTest.pipe?(io) assert_equal true, FileTest.pipe?(io)
assert_equal false, FileTest.pipe?("/tmp") rescue NotImplementedError => e
skip e.message
end
end end
assert('FileTest.size') do assert('FileTest.size') do
...@@ -61,11 +65,19 @@ assert("FileTest.size?") do ...@@ -61,11 +65,19 @@ assert("FileTest.size?") do
end end
assert("FileTest.socket?") do assert("FileTest.socket?") do
begin
assert_true FileTest.socket?($mrbtest_io_socketname) assert_true FileTest.socket?($mrbtest_io_socketname)
rescue NotImplementedError => e
skip e.message
end
end end
assert("FileTest.symlink?") do assert("FileTest.symlink?") do
begin
assert_true FileTest.symlink?($mrbtest_io_symlinkname) assert_true FileTest.symlink?($mrbtest_io_symlinkname)
rescue NotImplementedError => e
skip e.message
end
end end
assert("FileTest.zero?") do assert("FileTest.zero?") do
......
...@@ -359,6 +359,7 @@ assert('IO#gets - paragraph mode') do ...@@ -359,6 +359,7 @@ assert('IO#gets - paragraph mode') do
end end
assert('IO.popen') do assert('IO.popen') do
begin
io = IO.popen("ls") io = IO.popen("ls")
assert_true io.close_on_exec? assert_true io.close_on_exec?
assert_equal Fixnum, io.pid.class assert_equal Fixnum, io.pid.class
...@@ -368,6 +369,9 @@ assert('IO.popen') do ...@@ -368,6 +369,9 @@ assert('IO.popen') do
assert_include ls, 'mrblib' assert_include ls, 'mrblib'
io.close io.close
io.closed? io.closed?
rescue NotImplementedError => e
skip e.message
end
end end
assert('IO.read') do assert('IO.read') do
...@@ -450,6 +454,7 @@ assert('IO#sysseek') do ...@@ -450,6 +454,7 @@ assert('IO#sysseek') do
end end
assert('IO.pipe') do assert('IO.pipe') do
begin
called = false called = false
IO.pipe do |r, w| IO.pipe do |r, w|
assert_true r.kind_of?(IO) assert_true r.kind_of?(IO)
...@@ -483,10 +488,17 @@ assert('IO.pipe') do ...@@ -483,10 +488,17 @@ assert('IO.pipe') do
assert_nothing_raised do assert_nothing_raised do
IO.pipe { |r, w| r.close; w.close } IO.pipe { |r, w| r.close; w.close }
end end
rescue NotImplementedError => e
skip e.message
end
end end
assert('`cmd`') do assert('`cmd`') do
begin
assert_equal `echo foo`, "foo\n" assert_equal `echo foo`, "foo\n"
rescue NotImplementedError => e
skip e.message
end
end end
assert('IO TEST CLEANUP') do assert('IO TEST CLEANUP') do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment