Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions src/crystal/system.cr

This file was deleted.

20 changes: 0 additions & 20 deletions src/crystal/system/random.cr

This file was deleted.

11 changes: 0 additions & 11 deletions src/crystal/system/time.cr

This file was deleted.

8 changes: 8 additions & 0 deletions src/platform_specific/random.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% if flag?(:linux) %}
require "./unix/getrandom"
{% elsif flag?(:openbsd) %}
require "./unix/arc4random"
{% else %}
# TODO: restrict on flag?(:unix) after crystal > 0.22.0 is released
require "./unix/urandom"
{% end %}
8 changes: 8 additions & 0 deletions src/platform_specific/system.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require "./unix/hostname"

{% if flag?(:freebsd) || flag?(:openbsd) %}
require "./unix/sysctl_cpucount"
{% else %}
# TODO: restrict on flag?(:unix) after crystal > 0.22.0 is released
require "./unix/sysconf_cpucount"
{% end %}
1 change: 1 addition & 0 deletions src/platform_specific/time.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require "./unix/time"
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

require "c/stdlib"

module Crystal::System::Random
# Fills *buffer* with random bytes using arc4random.
#
# NOTE: only secure on OpenBSD and CloudABI
module Random::System
def self.random_bytes(buffer : Bytes) : Nil
# Fills *buffer* with random bytes using arc4random.
#
# NOTE: only secure on OpenBSD and CloudABI
LibC.arc4random_buf(buffer.to_unsafe.as(Void*), buffer.size)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require "c/unistd"
require "c/sys/syscall"

module Crystal::System::Random
module Random::System
@@initialized = false
@@getrandom_available = false
@@urandom : File?
Expand All @@ -23,8 +23,8 @@ module Crystal::System::Random
end
end

# Reads n random bytes using the Linux `getrandom(2)` syscall.
def self.random_bytes(buf : Bytes) : Nil
# Reads n random bytes using the Linux `getrandom(2)` syscall.
init unless @@initialized

if @@getrandom_available
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "c/unistd"

module Crystal::System
module System
def self.hostname
String.new(255) do |buffer|
unless LibC.gethostname(buffer, LibC::SizeT.new(255)) == 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require "c/unistd"

module Crystal::System
module System
def self.cpu_count
LibC.sysconf(LibC::SC_NPROCESSORS_ONLN)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require "c/sysctl"

module Crystal::System
module System
def self.cpu_count
mib = Int32[LibC::CTL_HW, LibC::HW_NCPU]
ncpus = 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
require "c/sys/time"
require "c/time"

module Crystal::System::Time
struct Time
UnixEpochInSeconds = 62135596800_i64

def self.compute_utc_offset(seconds : Int64) : Int64
private def self.compute_utc_offset(seconds : Int64) : Int64
LibC.tzset
offset = nil

Expand All @@ -26,7 +26,7 @@ module Crystal::System::Time
offset
end

def self.compute_utc_second_and_tenth_microsecond : {Int64, Int64}
private def self.compute_utc_second_and_tenth_microsecond : {Int64, Int64}
{% if LibC.methods.includes?("clock_gettime".id) %}
ret = LibC.clock_gettime(LibC::CLOCK_REALTIME, out timespec)
raise Errno.new("clock_gettime") unless ret == 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# TODO: replace with `flag?(:unix) && !flag?(:openbsd) && !flag?(:linux)` after crystal > 0.22.0 is released
{% skip_file() if flag?(:openbsd) && flag?(:linux) %}

module Crystal::System::Random
module Random::System
@@initialized = false
@@urandom : File?

Expand Down
4 changes: 2 additions & 2 deletions src/random/isaac.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "crystal/system/random"
require "random/system"

# (c) Bob Jenkins, March 1996, Public Domain
# You may use this code in any way you wish, and it is free. No warrantee.
Expand All @@ -17,7 +17,7 @@ class Random::ISAAC
private def random_seeds
result = uninitialized Seeds
result_slice = result.unsafe_as(StaticArray(UInt8, sizeof(Seeds))).to_slice
Crystal::System::Random.random_bytes(result_slice)
Random::System.random_bytes(result_slice)
result
end

Expand Down
27 changes: 18 additions & 9 deletions src/random/system.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require "crystal/system/random"

# Generates random numbers from a secure source of the system.
#
# For example `arc4random` is used on OpenBSD, whereas on Linux it uses
Expand All @@ -12,17 +10,26 @@ require "crystal/system/random"
# ```
module Random::System
extend Random
extend self

def next_u
Crystal::System::Random.next_u
# Fills *buffer* with random bytes from a secure source.
def self.random_bytes(buffer : Bytes) : Nil
{% raise "Not implemented for this system" %}
end

# Returns a random unsigned integer from a secure source. Implementations
# may choose the integer size to return based on what the system source
# provides. They may choose to return a single byte (UInt8) in which case
# `::Random` will prefer `#random_bytes` to read as many bytes as required
# at once, avoiding multiple reads or reading too many bytes.
def self.next_u
{% raise "Not implemented for this system" %}
end

{% for type in [UInt8, UInt16, UInt32, UInt64] %}
# Generates a random integer of a given type. The number of bytes to
# generate can be limited; by default it will generate as many bytes as
# needed to fill the integer size.
private def rand_type(type : {{type}}.class, needed_parts = nil) : {{type}}
private def self.rand_type(type : {{type}}.class, needed_parts = nil) : {{type}}
needed_bytes =
if needed_parts
needed_parts * sizeof(typeof(next_u))
Expand All @@ -34,22 +41,24 @@ module Random::System

if needed_bytes < sizeof({{type}})
bytes = Slice.new(buf.to_unsafe, needed_bytes)
Crystal::System::Random.random_bytes(bytes)
random_bytes(bytes)

bytes.reduce({{type}}.new(0)) do |result, byte|
(result << 8) | byte
end
else
Crystal::System::Random.random_bytes(buf.to_slice)
random_bytes(buf.to_slice)
buf.to_unsafe.as({{type}}*).value
end
end
{% end %}

{% for type in [Int8, Int16, Int32, Int64] %}
private def rand_type(type : {{type}}.class, needed_bytes = sizeof({{type}})) : {{type}}
private def self.rand_type(type : {{type}}.class, needed_bytes = sizeof({{type}})) : {{type}}
result = rand_type({{"U#{type}".id}}, needed_bytes)
{{type}}.new(result)
end
{% end %}
end

require "platform_specific/random"
3 changes: 1 addition & 2 deletions src/secure_random.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require "base64"
require "crystal/system/random"

# The `SecureRandom` module is an interface for creating cryptography secure
# random values in different formats.
Expand Down Expand Up @@ -74,7 +73,7 @@ module SecureRandom
# slice # => [217, 118, 38, 196]
# ```
def self.random_bytes(buf : Bytes) : Nil
Crystal::System::Random.random_bytes(buf)
Random::System.random_bytes(buf)
end

# Generates a UUID (Universally Unique Identifier).
Expand Down
8 changes: 4 additions & 4 deletions src/system.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require "crystal/system"

module System
# Returns the hostname.
#
Expand All @@ -11,7 +9,7 @@ module System
# System.hostname # => "host.example.org"
# ```
def self.hostname
Crystal::System.hostname
{% raise "Not implemented for this system" %}
end

# Returns the number of logical processors available to the system.
Expand All @@ -20,6 +18,8 @@ module System
# System.cpu_count # => 4
# ```
def self.cpu_count
Crystal::System.cpu_count
{% raise "Not implemented for this system" %}
end
end

require "platform_specific/system"
19 changes: 15 additions & 4 deletions src/time.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require "crystal/system/time"

# `Time` represents an instance in time. Here are some examples:
#
# ### Basic Usage
Expand Down Expand Up @@ -600,12 +598,25 @@ struct Time
end

private def self.compute_offset(second)
Crystal::System::Time.compute_utc_offset(second) / 60 * Span::TicksPerMinute
compute_utc_offset(second) / 60 * Span::TicksPerMinute
end

private def self.compute_second_and_tenth_microsecond
Crystal::System::Time.compute_utc_second_and_tenth_microsecond
compute_utc_second_and_tenth_microsecond
end

# Returns the number of seconds that you must add to UTC to get local time.
# *seconds* are measured from `0001-01-01 00:00:00`.
private def self.compute_utc_offset(seconds : Int64) : Int64
{% raise "Not implemented for this system" %}
end

# Returns the current UTC time measured in `{seconds, tenth_microsecond}`
# since `0001-01-01 00:00:00`.
private def self.compute_utc_second_and_tenth_microsecond : {Int64, Int64}
{% raise "Not implemented for this system" %}
end
end

require "./time/**"
require "platform_specific/time"