-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy patherrno.cr
99 lines (92 loc) · 3.61 KB
/
errno.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
require "c/errno"
require "c/string"
lib LibC
{% if flag?(:netbsd) || flag?(:openbsd) || flag?(:android) %}
fun __errno : Int*
{% elsif flag?(:solaris) %}
fun ___errno : Int*
{% elsif flag?(:linux) || flag?(:dragonfly) %}
fun __errno_location : Int*
{% elsif flag?(:wasi) %}
$errno : Int
{% elsif flag?(:darwin) || flag?(:freebsd) %}
fun __error : Int*
{% elsif flag?(:win32) %}
fun _get_errno(value : Int*) : ErrnoT
fun _set_errno(value : Int) : ErrnoT
{% end %}
end
# Errno wraps and gives access to libc's errno. This is mostly useful when
# dealing with C libraries.
enum Errno
NONE = 0
{% for value in %w(E2BIG EPERM ENOENT ESRCH EINTR EIO ENXIO ENOEXEC EBADF ECHILD EDEADLK ENOMEM
EACCES EFAULT ENOTBLK EBUSY EEXIST EXDEV ENODEV ENOTDIR EISDIR EINVAL ENFILE
EMFILE ENOTTY ETXTBSY EFBIG ENOSPC ESPIPE EROFS EMLINK EPIPE EDOM ERANGE EAGAIN
EWOULDBLOCK EINPROGRESS EALREADY ENOTSOCK EDESTADDRREQ EMSGSIZE EPROTOTYPE ENOPROTOOPT
EPROTONOSUPPORT ESOCKTNOSUPPORT EPFNOSUPPORT EAFNOSUPPORT EADDRINUSE EADDRNOTAVAIL
ENETDOWN ENETUNREACH ENETRESET ECONNABORTED ECONNRESET ENOBUFS EISCONN ENOTCONN
ESHUTDOWN ETOOMANYREFS ETIMEDOUT ECONNREFUSED ELOOP ENAMETOOLONG EHOSTDOWN
EHOSTUNREACH ENOTEMPTY EUSERS EDQUOT ESTALE EREMOTE ENOLCK ENOSYS EOVERFLOW
ECANCELED EIDRM ENOMSG EILSEQ EBADMSG EMULTIHOP ENODATA ENOLINK ENOSR ENOSTR
EPROTO ETIME EOPNOTSUPP ENOTRECOVERABLE EOWNERDEAD) %}
{% if LibC.has_constant?(value) %}
{{value.id}} = LibC::{{value.id}}
{% end %}
{% end %}
# Returns the system error message associated with this errno.
#
# NOTE: The result may depend on the current system locale. Specs and
# comparisons should use `#value` instead of this method.
def message : String
unsafe_message { |slice| String.new(slice) }
end
# :nodoc:
def unsafe_message(&)
{% if LibC.has_method?(:strerror_r) %}
buffer = uninitialized UInt8[256]
if LibC.strerror_r(value, buffer, buffer.size) == 0
yield Bytes.new(buffer.to_unsafe, LibC.strlen(buffer))
else
yield "(???)".to_slice
end
{% else %}
pointer = LibC.strerror(value)
yield Bytes.new(pointer, LibC.strlen(pointer))
{% end %}
end
# returns the value of libc's errno.
def self.value : self
{% if flag?(:netbsd) || flag?(:openbsd) || flag?(:android) %}
Errno.new LibC.__errno.value
{% elsif flag?(:solaris) %}
Errno.new LibC.___errno.value
{% elsif flag?(:linux) || flag?(:dragonfly) %}
Errno.new LibC.__errno_location.value
{% elsif flag?(:wasi) %}
Errno.new LibC.errno
{% elsif flag?(:darwin) || flag?(:freebsd) %}
Errno.new LibC.__error.value
{% elsif flag?(:win32) %}
ret = LibC._get_errno(out errno)
raise RuntimeError.from_os_error("_get_errno", Errno.new(ret)) unless ret == 0
Errno.new errno
{% end %}
end
# Sets the value of libc's errno.
def self.value=(errno : Errno)
{% if flag?(:netbsd) || flag?(:openbsd) || flag?(:android) %}
LibC.__errno.value = errno.value
{% elsif flag?(:solaris) %}
LibC.___errno.value = errno.value
{% elsif flag?(:linux) || flag?(:dragonfly) %}
LibC.__errno_location.value = errno.value
{% elsif flag?(:darwin) || flag?(:freebsd) %}
LibC.__error.value = errno.value
{% elsif flag?(:win32) %}
ret = LibC._set_errno(errno.value)
raise RuntimeError.from_os_error("_set_errno", Errno.new(ret)) unless ret == 0
{% end %}
errno
end
end