aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/syscall/syscall_libc_darwin.go
blob: d64f1061f3405ada2f3a01ff9e1417a2218c2f5f (plain)
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
//go:build darwin

package syscall

import (
	"internal/itoa"
	"unsafe"
)

// This file defines errno and constants to match the darwin libsystem ABI.
// Values have been copied from src/syscall/zerrors_darwin_amd64.go.

// This function returns the error location in the darwin ABI.
// Discovered by compiling the following code using Clang:
//
//	#include <errno.h>
//	int getErrno() {
//	    return errno;
//	}
//
//export __error
func libc___error() *int32

// getErrno returns the current C errno. It may not have been caused by the last
// call, so it should only be relied upon when the last call indicates an error
// (for example, by returning -1).
func getErrno() Errno {
	errptr := libc___error()
	return Errno(uintptr(*errptr))
}

func (e Errno) Is(target error) bool {
	switch target.Error() {
	case "permission denied":
		return e == EACCES || e == EPERM
	case "file already exists":
		return e == EEXIST
	case "file does not exist":
		return e == ENOENT
	}
	return false
}

// Source: upstream zerrors_darwin_amd64.go
const (
	DT_BLK     = 0x6
	DT_CHR     = 0x2
	DT_DIR     = 0x4
	DT_FIFO    = 0x1
	DT_LNK     = 0xa
	DT_REG     = 0x8
	DT_SOCK    = 0xc
	DT_UNKNOWN = 0x0
	DT_WHT     = 0xe
	F_GETFL    = 0x3
	F_SETFL    = 0x4
	O_NONBLOCK = 0x4
)

// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/errno.h.auto.html
const (
	EPERM       Errno = 1
	ENOENT      Errno = 2
	EACCES      Errno = 13
	EEXIST      Errno = 17
	EINTR       Errno = 4
	ENOTDIR     Errno = 20
	EISDIR      Errno = 21
	EINVAL      Errno = 22
	EMFILE      Errno = 24
	EROFS       Errno = 30
	EPIPE       Errno = 32
	EAGAIN      Errno = 35
	ENOTCONN    Errno = 57
	ETIMEDOUT   Errno = 60
	ENOSYS      Errno = 78
	EWOULDBLOCK Errno = EAGAIN
)

type Signal int

// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/signal.h
const (
	SIGINT  Signal = 2  /* interrupt */
	SIGQUIT Signal = 3  /* quit */
	SIGILL  Signal = 4  /* illegal instruction (not reset when caught) */
	SIGTRAP Signal = 5  /* trace trap (not reset when caught) */
	SIGABRT Signal = 6  /* abort() */
	SIGFPE  Signal = 8  /* floating point exception */
	SIGKILL Signal = 9  /* kill (cannot be caught or ignored) */
	SIGBUS  Signal = 10 /* bus error */
	SIGSEGV Signal = 11 /* segmentation violation */
	SIGPIPE Signal = 13 /* write on a pipe with no one to read it */
	SIGTERM Signal = 15 /* software termination signal from kill */
	SIGCHLD Signal = 20 /* to parent on child stop or exit */
)

func (s Signal) Signal() {}

func (s Signal) String() string {
	if 0 <= s && int(s) < len(signals) {
		str := signals[s]
		if str != "" {
			return str
		}
	}
	return "signal " + itoa.Itoa(int(s))
}

var signals = [...]string{}

const (
	Stdin  = 0
	Stdout = 1
	Stderr = 2
)

const (
	O_RDONLY = 0x0
	O_WRONLY = 0x1
	O_RDWR   = 0x2
	O_APPEND = 0x8
	O_SYNC   = 0x80
	O_CREAT  = 0x200
	O_TRUNC  = 0x400
	O_EXCL   = 0x800

	O_CLOEXEC = 0x01000000
)

// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/mman.h.auto.html
const (
	PROT_NONE  = 0x00 // no permissions
	PROT_READ  = 0x01 // pages can be read
	PROT_WRITE = 0x02 // pages can be written
	PROT_EXEC  = 0x04 // pages can be executed

	MAP_SHARED  = 0x0001 // share changes
	MAP_PRIVATE = 0x0002 // changes are private

	MAP_FILE      = 0x0000 // map from file (default)
	MAP_ANON      = 0x1000 // allocated from memory, swap space
	MAP_ANONYMOUS = MAP_ANON
)

type Timespec struct {
	Sec  int64
	Nsec int64
}

// Unix returns the time stored in ts as seconds plus nanoseconds.
func (ts *Timespec) Unix() (sec int64, nsec int64) {
	return int64(ts.Sec), int64(ts.Nsec)
}

// Source: upstream ztypes_darwin_amd64.go
type Dirent struct {
	Ino       uint64
	Seekoff   uint64
	Reclen    uint16
	Namlen    uint16
	Type      uint8
	Name      [1024]int8
	Pad_cgo_0 [3]byte
}

type Stat_t struct {
	Dev       int32
	Mode      uint16
	Nlink     uint16
	Ino       uint64
	Uid       uint32
	Gid       uint32
	Rdev      int32
	Pad_cgo_0 [4]byte
	Atimespec Timespec
	Mtimespec Timespec
	Ctimespec Timespec
	Btimespec Timespec
	Size      int64
	Blocks    int64
	Blksize   int32
	Flags     uint32
	Gen       uint32
	Lspare    int32
	Qspare    [2]int64
}

// Source: https://github.com/apple/darwin-xnu/blob/main/bsd/sys/_types/_s_ifmt.h
const (
	S_IEXEC  = 0x40
	S_IFBLK  = 0x6000
	S_IFCHR  = 0x2000
	S_IFDIR  = 0x4000
	S_IFIFO  = 0x1000
	S_IFLNK  = 0xa000
	S_IFMT   = 0xf000
	S_IFREG  = 0x8000
	S_IFSOCK = 0xc000
	S_IFWHT  = 0xe000
	S_IREAD  = 0x100
	S_IRGRP  = 0x20
	S_IROTH  = 0x4
	S_IRUSR  = 0x100
	S_IRWXG  = 0x38
	S_IRWXO  = 0x7
	S_IRWXU  = 0x1c0
	S_ISGID  = 0x400
	S_ISTXT  = 0x200
	S_ISUID  = 0x800
	S_ISVTX  = 0x200
	S_IWGRP  = 0x10
	S_IWOTH  = 0x2
	S_IWRITE = 0x80
	S_IWUSR  = 0x80
	S_IXGRP  = 0x8
	S_IXOTH  = 0x1
	S_IXUSR  = 0x40
)

func Stat(path string, p *Stat_t) (err error) {
	data := cstring(path)
	n := libc_stat(&data[0], unsafe.Pointer(p))

	if n < 0 {
		err = getErrno()
	}
	return
}

func Fstat(fd int, p *Stat_t) (err error) {
	n := libc_fstat(int32(fd), unsafe.Pointer(p))

	if n < 0 {
		err = getErrno()
	}
	return
}

func Lstat(path string, p *Stat_t) (err error) {
	data := cstring(path)
	n := libc_lstat(&data[0], unsafe.Pointer(p))
	if n < 0 {
		err = getErrno()
	}
	return
}

func Fdopendir(fd int) (dir uintptr, err error) {
	r0 := libc_fdopendir(int32(fd))
	dir = uintptr(r0)
	if dir == 0 {
		err = getErrno()
	}
	return
}

func Pipe2(fds []int, flags int) (err error) {
	// Mac only has Pipe, which ignores the flags argument
	buf := make([]int32, 2)
	fail := int(libc_pipe(&buf[0]))
	if fail < 0 {
		err = getErrno()
	} else {
		fds[0] = int(buf[0])
		fds[1] = int(buf[1])
	}
	return
}

func Chmod(path string, mode uint32) (err error) {
	data := cstring(path)
	fail := int(libc_chmod(&data[0], mode))
	if fail < 0 {
		err = getErrno()
	}
	return
}

func closedir(dir uintptr) (err error) {
	e := libc_closedir(unsafe.Pointer(dir))
	if e != 0 {
		err = getErrno()
	}
	return
}

func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (err error) {
	e1 := libc_readdir_r(unsafe.Pointer(dir), unsafe.Pointer(entry), unsafe.Pointer(result))
	if e1 != 0 {
		err = getErrno()
	}
	return
}

func Getpagesize() int {
	return int(libc_getpagesize())
}

// The following RawSockAddr* types have been copied from the Go source tree and
// are here purely to fix build errors.

type RawSockaddr struct {
	Len    uint8
	Family uint8
	Data   [14]int8
}

type RawSockaddrInet4 struct {
	Len    uint8
	Family uint8
	Port   uint16
	Addr   [4]byte /* in_addr */
	Zero   [8]int8
}

type RawSockaddrInet6 struct {
	Len      uint8
	Family   uint8
	Port     uint16
	Flowinfo uint32
	Addr     [16]byte /* in6_addr */
	Scope_id uint32
}

// int pipe(int32 *fds);
//
//export pipe
func libc_pipe(fds *int32) int32

// int getpagesize();
//
//export getpagesize
func libc_getpagesize() int32

// int open(const char *pathname, int flags, mode_t mode);
//
//export syscall_libc_open
func libc_open(pathname *byte, flags int32, mode uint32) int32