Skip to content

Commit

Permalink
Implement Crystal::System::FileDescriptor for windows
Browse files Browse the repository at this point in the history
  • Loading branch information
RX14 committed Dec 19, 2017
1 parent 0412e13 commit 29c9b9e
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 18 deletions.
6 changes: 5 additions & 1 deletion src/crystal/system/file_descriptor.cr
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
require "./unix/file_descriptor"
{% if flag?(:win32) %}
require "./win32/file_descriptor"
{% else %}
require "./unix/file_descriptor"
{% end %}
98 changes: 98 additions & 0 deletions src/crystal/system/win32/file_descriptor.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
require "file/stat"
require "c/io"

module Crystal::System::FileDescriptor
@fd : LibC::Int

private def unbuffered_read(slice : Bytes)
bytes_read = LibC._read(@fd, slice, slice.size)
if bytes_read == -1
raise Errno.new("Error reading file")
end
bytes_read
end

private def unbuffered_write(slice : Bytes)
loop do
bytes_written = LibC._write(@fd, slice, slice.size)
if bytes_written == -1
raise Errno.new("Error writing file")
end

slice += bytes_written
return if slice.size == 0
end
end

private def system_blocking?
true
end

private def system_blocking=(value)
raise NotImplemented.new if value
end

private def system_close_on_exec?
false
end

private def system_close_on_exec=(value)
raise NotImplemented.new if value
end

private def system_stat
if LibC._fstat64(@fd, out stat) != 0
raise Errno.new("Unable to get stat")
end
::File::Stat.new(stat)
end

private def system_seek(offset, whence : IO::Seek) : Nil
seek_value = LibC._lseek(@fd, offset, whence)

if seek_value == -1
raise Errno.new "Unable to seek"
end
end

private def system_pos
pos = LibC._lseek(@fd, 0, IO::Seek::Current)
raise Errno.new "Unable to tell" if pos == -1
pos
end

private def system_tty?
LibC._isatty(@fd) != 0
end

private def system_reopen(other : IO::FileDescriptor)
{% if LibC.methods.includes? "dup3".id %}
# dup doesn't copy the CLOEXEC flag, so copy it manually using dup3
flags = other.close_on_exec? ? LibC::O_CLOEXEC : 0
if LibC.dup3(other.fd, self.fd, flags) == -1
raise Errno.new("Could not reopen file descriptor")
end
{% else %}
# dup doesn't copy the CLOEXEC flag, copy it manually to the new
if LibC.dup2(other.fd, self.fd) == -1
raise Errno.new("Could not reopen file descriptor")
end

if other.close_on_exec?
self.close_on_exec = true
end
{% end %}
end

private def system_close
err = nil
if LibC._close(@fd) != 0
case Errno.value
when Errno::EINTR
# ignore
else
raise Errno.new("Error closing file")
end
end
end
end
63 changes: 46 additions & 17 deletions src/file/stat.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,51 @@ require "c/sys/stat"

class File
struct Stat
def initialize(filename : String)
if LibC.stat(filename, out @stat) != 0
raise Errno.new("Unable to get stat for '#{filename}'")
end
def self.new(filename : String)
File.stat(filename)
end

def initialize(@stat : LibC::Stat)
end
{% if flag?(:win32) %}
# :nodoc:
def initialize(@stat : LibC::Stat64)
end
{% else %}
# :nodoc:
def initialize(@stat : LibC::Stat)
end
{% end %}

def atime
{% if flag?(:darwin) %}
time @stat.st_atimespec
{% elsif flag?(:win32) %}
time @stat.st_atime
{% else %}
time @stat.st_atim
{% end %}
end

def blksize
@stat.st_blksize
{% if flag?(:win32) %}
raise NotImplemented.new
{% else %}
@stat.st_blksize
{% end %}
end

def blocks
@stat.st_blocks
{% if flag?(:win32) %}
raise NotImplemented.new
{% else %}
@stat.st_blocks
{% end %}
end

def ctime
{% if flag?(:darwin) %}
time @stat.st_ctimespec
{% elsif flag?(:win32) %}
time @stat.st_ctime
{% else %}
time @stat.st_ctim
{% end %}
Expand Down Expand Up @@ -59,6 +76,8 @@ class File
def mtime
{% if flag?(:darwin) %}
time @stat.st_mtimespec
{% elsif flag?(:win32) %}
time @stat.st_mtime
{% else %}
time @stat.st_mtim
{% end %}
Expand Down Expand Up @@ -93,8 +112,10 @@ class File
io << ", rdev=0x"
rdev.to_s(16, io)
io << ", size=" << size
io << ", blksize=" << blksize
io << ", blocks=" << blocks
{% unless flag?(:win32) %}
io << ", blksize=" << blksize
io << ", blocks=" << blocks
{% end %}
io << ", atime=" << atime
io << ", mtime=" << mtime
io << ", ctime=" << ctime
Expand All @@ -119,10 +140,12 @@ class File
pp.comma
pp.text "size=#{size}"
pp.comma
pp.text "blksize=#{blksize}"
pp.comma
pp.text "blocks=#{blocks}"
pp.comma
{% unless flag?(:win32) %}
pp.text "blksize=#{blksize}"
pp.comma
pp.text "blocks=#{blocks}"
pp.comma
{% end %}
pp.text "atime=#{atime}"
pp.comma
pp.text "mtime=#{mtime}"
Expand Down Expand Up @@ -171,8 +194,14 @@ class File
(@stat.st_mode & LibC::S_IFMT) == LibC::S_ISVTX
end

private def time(value)
Time.new value, Time::Kind::Utc
end
{% if flag?(:win32) %}
private def time(value)
Time.epoch(value)
end
{% else %}
private def time(value)
Time.new value, Time::Kind::Utc
end
{% end %}
end
end

0 comments on commit 29c9b9e

Please sign in to comment.