all repos

rss-tools @ a5ac52722b131734c74504b6e6f4d9900536cac7

get rss feed from sources that(i need and) dont provide one

rss-tools/vendor/golang.org/x/sys/unix/syscall_solaris.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
we're vendoring now, 7 days ago
1
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
5
// Solaris system calls.
6
// This file is compiled as ordinary Go code,
7
// but it is also input to mksyscall,
8
// which parses the //sys lines and generates system call stubs.
9
// Note that sometimes we use a lowercase //sys name and wrap
10
// it in our own nicer implementation, either here or in
11
// syscall_solaris.go or syscall_unix.go.
12
13
package unix
14
15
import (
16
	"fmt"
17
	"os"
18
	"runtime"
19
	"sync"
20
	"syscall"
21
	"unsafe"
22
)
23
24
// Implemented in runtime/syscall_solaris.go.
25
type syscallFunc uintptr
26
27
func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
28
func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
29
30
// SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
31
type SockaddrDatalink struct {
32
	Family uint16
33
	Index  uint16
34
	Type   uint8
35
	Nlen   uint8
36
	Alen   uint8
37
	Slen   uint8
38
	Data   [244]int8
39
	raw    RawSockaddrDatalink
40
}
41
42
func direntIno(buf []byte) (uint64, bool) {
43
	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
44
}
45
46
func direntReclen(buf []byte) (uint64, bool) {
47
	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
48
}
49
50
func direntNamlen(buf []byte) (uint64, bool) {
51
	reclen, ok := direntReclen(buf)
52
	if !ok {
53
		return 0, false
54
	}
55
	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
56
}
57
58
//sysnb	pipe(p *[2]_C_int) (n int, err error)
59
60
func Pipe(p []int) (err error) {
61
	if len(p) != 2 {
62
		return EINVAL
63
	}
64
	var pp [2]_C_int
65
	n, err := pipe(&pp)
66
	if n != 0 {
67
		return err
68
	}
69
	if err == nil {
70
		p[0] = int(pp[0])
71
		p[1] = int(pp[1])
72
	}
73
	return nil
74
}
75
76
//sysnb	pipe2(p *[2]_C_int, flags int) (err error)
77
78
func Pipe2(p []int, flags int) error {
79
	if len(p) != 2 {
80
		return EINVAL
81
	}
82
	var pp [2]_C_int
83
	err := pipe2(&pp, flags)
84
	if err == nil {
85
		p[0] = int(pp[0])
86
		p[1] = int(pp[1])
87
	}
88
	return err
89
}
90
91
func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
92
	if sa.Port < 0 || sa.Port > 0xFFFF {
93
		return nil, 0, EINVAL
94
	}
95
	sa.raw.Family = AF_INET
96
	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
97
	p[0] = byte(sa.Port >> 8)
98
	p[1] = byte(sa.Port)
99
	sa.raw.Addr = sa.Addr
100
	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
101
}
102
103
func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
104
	if sa.Port < 0 || sa.Port > 0xFFFF {
105
		return nil, 0, EINVAL
106
	}
107
	sa.raw.Family = AF_INET6
108
	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
109
	p[0] = byte(sa.Port >> 8)
110
	p[1] = byte(sa.Port)
111
	sa.raw.Scope_id = sa.ZoneId
112
	sa.raw.Addr = sa.Addr
113
	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
114
}
115
116
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
117
	name := sa.Name
118
	n := len(name)
119
	if n >= len(sa.raw.Path) {
120
		return nil, 0, EINVAL
121
	}
122
	sa.raw.Family = AF_UNIX
123
	for i := 0; i < n; i++ {
124
		sa.raw.Path[i] = int8(name[i])
125
	}
126
	// length is family (uint16), name, NUL.
127
	sl := _Socklen(2)
128
	if n > 0 {
129
		sl += _Socklen(n) + 1
130
	}
131
	if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
132
		// Check sl > 3 so we don't change unnamed socket behavior.
133
		sa.raw.Path[0] = 0
134
		// Don't count trailing NUL for abstract address.
135
		sl--
136
	}
137
138
	return unsafe.Pointer(&sa.raw), sl, nil
139
}
140
141
//sys	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname
142
143
func Getsockname(fd int) (sa Sockaddr, err error) {
144
	var rsa RawSockaddrAny
145
	var len _Socklen = SizeofSockaddrAny
146
	if err = getsockname(fd, &rsa, &len); err != nil {
147
		return
148
	}
149
	return anyToSockaddr(fd, &rsa)
150
}
151
152
// GetsockoptString returns the string value of the socket option opt for the
153
// socket associated with fd at the given socket level.
154
func GetsockoptString(fd, level, opt int) (string, error) {
155
	buf := make([]byte, 256)
156
	vallen := _Socklen(len(buf))
157
	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
158
	if err != nil {
159
		return "", err
160
	}
161
	return ByteSliceToString(buf[:vallen]), nil
162
}
163
164
const ImplementsGetwd = true
165
166
//sys	Getcwd(buf []byte) (n int, err error)
167
168
func Getwd() (wd string, err error) {
169
	var buf [PathMax]byte
170
	// Getcwd will return an error if it failed for any reason.
171
	_, err = Getcwd(buf[0:])
172
	if err != nil {
173
		return "", err
174
	}
175
	n := clen(buf[:])
176
	if n < 1 {
177
		return "", EINVAL
178
	}
179
	return string(buf[:n]), nil
180
}
181
182
/*
183
 * Wrapped
184
 */
185
186
//sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
187
//sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
188
189
func Getgroups() (gids []int, err error) {
190
	n, err := getgroups(0, nil)
191
	// Check for error and sanity check group count. Newer versions of
192
	// Solaris allow up to 1024 (NGROUPS_MAX).
193
	if n < 0 || n > 1024 {
194
		if err != nil {
195
			return nil, err
196
		}
197
		return nil, EINVAL
198
	} else if n == 0 {
199
		return nil, nil
200
	}
201
202
	a := make([]_Gid_t, n)
203
	n, err = getgroups(n, &a[0])
204
	if n == -1 {
205
		return nil, err
206
	}
207
	gids = make([]int, n)
208
	for i, v := range a[0:n] {
209
		gids[i] = int(v)
210
	}
211
	return
212
}
213
214
func Setgroups(gids []int) (err error) {
215
	if len(gids) == 0 {
216
		return setgroups(0, nil)
217
	}
218
219
	a := make([]_Gid_t, len(gids))
220
	for i, v := range gids {
221
		a[i] = _Gid_t(v)
222
	}
223
	return setgroups(len(a), &a[0])
224
}
225
226
// ReadDirent reads directory entries from fd and writes them into buf.
227
func ReadDirent(fd int, buf []byte) (n int, err error) {
228
	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
229
	// TODO(rsc): Can we use a single global basep for all calls?
230
	return Getdents(fd, buf, new(uintptr))
231
}
232
233
// Wait status is 7 bits at bottom, either 0 (exited),
234
// 0x7F (stopped), or a signal number that caused an exit.
235
// The 0x80 bit is whether there was a core dump.
236
// An extra number (exit code, signal causing a stop)
237
// is in the high bits.
238
239
type WaitStatus uint32
240
241
const (
242
	mask  = 0x7F
243
	core  = 0x80
244
	shift = 8
245
246
	exited  = 0
247
	stopped = 0x7F
248
)
249
250
func (w WaitStatus) Exited() bool { return w&mask == exited }
251
252
func (w WaitStatus) ExitStatus() int {
253
	if w&mask != exited {
254
		return -1
255
	}
256
	return int(w >> shift)
257
}
258
259
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
260
261
func (w WaitStatus) Signal() syscall.Signal {
262
	sig := syscall.Signal(w & mask)
263
	if sig == stopped || sig == 0 {
264
		return -1
265
	}
266
	return sig
267
}
268
269
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
270
271
func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
272
273
func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
274
275
func (w WaitStatus) StopSignal() syscall.Signal {
276
	if !w.Stopped() {
277
		return -1
278
	}
279
	return syscall.Signal(w>>shift) & 0xFF
280
}
281
282
func (w WaitStatus) TrapCause() int { return -1 }
283
284
//sys	wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error)
285
286
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
287
	var status _C_int
288
	rpid, err := wait4(int32(pid), &status, options, rusage)
289
	wpid := int(rpid)
290
	if wpid == -1 {
291
		return wpid, err
292
	}
293
	if wstatus != nil {
294
		*wstatus = WaitStatus(status)
295
	}
296
	return wpid, nil
297
}
298
299
//sys	gethostname(buf []byte) (n int, err error)
300
301
func Gethostname() (name string, err error) {
302
	var buf [MaxHostNameLen]byte
303
	n, err := gethostname(buf[:])
304
	if n != 0 {
305
		return "", err
306
	}
307
	n = clen(buf[:])
308
	if n < 1 {
309
		return "", EFAULT
310
	}
311
	return string(buf[:n]), nil
312
}
313
314
//sys	utimes(path string, times *[2]Timeval) (err error)
315
316
func Utimes(path string, tv []Timeval) (err error) {
317
	if tv == nil {
318
		return utimes(path, nil)
319
	}
320
	if len(tv) != 2 {
321
		return EINVAL
322
	}
323
	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
324
}
325
326
//sys	utimensat(fd int, path string, times *[2]Timespec, flag int) (err error)
327
328
func UtimesNano(path string, ts []Timespec) error {
329
	if ts == nil {
330
		return utimensat(AT_FDCWD, path, nil, 0)
331
	}
332
	if len(ts) != 2 {
333
		return EINVAL
334
	}
335
	return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
336
}
337
338
func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
339
	if ts == nil {
340
		return utimensat(dirfd, path, nil, flags)
341
	}
342
	if len(ts) != 2 {
343
		return EINVAL
344
	}
345
	return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
346
}
347
348
//sys	fcntl(fd int, cmd int, arg int) (val int, err error)
349
350
// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
351
func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
352
	valptr, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
353
	var err error
354
	if errno != 0 {
355
		err = errno
356
	}
357
	return int(valptr), err
358
}
359
360
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
361
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
362
	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
363
	if e1 != 0 {
364
		return e1
365
	}
366
	return nil
367
}
368
369
//sys	futimesat(fildes int, path *byte, times *[2]Timeval) (err error)
370
371
func Futimesat(dirfd int, path string, tv []Timeval) error {
372
	pathp, err := BytePtrFromString(path)
373
	if err != nil {
374
		return err
375
	}
376
	if tv == nil {
377
		return futimesat(dirfd, pathp, nil)
378
	}
379
	if len(tv) != 2 {
380
		return EINVAL
381
	}
382
	return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
383
}
384
385
// Solaris doesn't have an futimes function because it allows NULL to be
386
// specified as the path for futimesat. However, Go doesn't like
387
// NULL-style string interfaces, so this simple wrapper is provided.
388
func Futimes(fd int, tv []Timeval) error {
389
	if tv == nil {
390
		return futimesat(fd, nil, nil)
391
	}
392
	if len(tv) != 2 {
393
		return EINVAL
394
	}
395
	return futimesat(fd, nil, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
396
}
397
398
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
399
	switch rsa.Addr.Family {
400
	case AF_UNIX:
401
		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
402
		sa := new(SockaddrUnix)
403
		// Assume path ends at NUL.
404
		// This is not technically the Solaris semantics for
405
		// abstract Unix domain sockets -- they are supposed
406
		// to be uninterpreted fixed-size binary blobs -- but
407
		// everyone uses this convention.
408
		n := 0
409
		for n < len(pp.Path) && pp.Path[n] != 0 {
410
			n++
411
		}
412
		sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
413
		return sa, nil
414
415
	case AF_INET:
416
		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
417
		sa := new(SockaddrInet4)
418
		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
419
		sa.Port = int(p[0])<<8 + int(p[1])
420
		sa.Addr = pp.Addr
421
		return sa, nil
422
423
	case AF_INET6:
424
		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
425
		sa := new(SockaddrInet6)
426
		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
427
		sa.Port = int(p[0])<<8 + int(p[1])
428
		sa.ZoneId = pp.Scope_id
429
		sa.Addr = pp.Addr
430
		return sa, nil
431
	}
432
	return nil, EAFNOSUPPORT
433
}
434
435
//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept
436
437
func Accept(fd int) (nfd int, sa Sockaddr, err error) {
438
	var rsa RawSockaddrAny
439
	var len _Socklen = SizeofSockaddrAny
440
	nfd, err = accept(fd, &rsa, &len)
441
	if nfd == -1 {
442
		return
443
	}
444
	sa, err = anyToSockaddr(fd, &rsa)
445
	if err != nil {
446
		Close(nfd)
447
		nfd = 0
448
	}
449
	return
450
}
451
452
//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
453
454
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
455
	var msg Msghdr
456
	msg.Name = (*byte)(unsafe.Pointer(rsa))
457
	msg.Namelen = uint32(SizeofSockaddrAny)
458
	var dummy byte
459
	if len(oob) > 0 {
460
		// receive at least one normal byte
461
		if emptyIovecs(iov) {
462
			var iova [1]Iovec
463
			iova[0].Base = &dummy
464
			iova[0].SetLen(1)
465
			iov = iova[:]
466
		}
467
		msg.Accrightslen = int32(len(oob))
468
	}
469
	if len(iov) > 0 {
470
		msg.Iov = &iov[0]
471
		msg.SetIovlen(len(iov))
472
	}
473
	if n, err = recvmsg(fd, &msg, flags); n == -1 {
474
		return
475
	}
476
	oobn = int(msg.Accrightslen)
477
	return
478
}
479
480
//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
481
482
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
483
	var msg Msghdr
484
	msg.Name = (*byte)(unsafe.Pointer(ptr))
485
	msg.Namelen = uint32(salen)
486
	var dummy byte
487
	var empty bool
488
	if len(oob) > 0 {
489
		// send at least one normal byte
490
		empty = emptyIovecs(iov)
491
		if empty {
492
			var iova [1]Iovec
493
			iova[0].Base = &dummy
494
			iova[0].SetLen(1)
495
			iov = iova[:]
496
		}
497
		msg.Accrightslen = int32(len(oob))
498
	}
499
	if len(iov) > 0 {
500
		msg.Iov = &iov[0]
501
		msg.SetIovlen(len(iov))
502
	}
503
	if n, err = sendmsg(fd, &msg, flags); err != nil {
504
		return 0, err
505
	}
506
	if len(oob) > 0 && empty {
507
		n = 0
508
	}
509
	return n, nil
510
}
511
512
//sys	acct(path *byte) (err error)
513
514
func Acct(path string) (err error) {
515
	if len(path) == 0 {
516
		// Assume caller wants to disable accounting.
517
		return acct(nil)
518
	}
519
520
	pathp, err := BytePtrFromString(path)
521
	if err != nil {
522
		return err
523
	}
524
	return acct(pathp)
525
}
526
527
//sys	__makedev(version int, major uint, minor uint) (val uint64)
528
529
func Mkdev(major, minor uint32) uint64 {
530
	return __makedev(NEWDEV, uint(major), uint(minor))
531
}
532
533
//sys	__major(version int, dev uint64) (val uint)
534
535
func Major(dev uint64) uint32 {
536
	return uint32(__major(NEWDEV, dev))
537
}
538
539
//sys	__minor(version int, dev uint64) (val uint)
540
541
func Minor(dev uint64) uint32 {
542
	return uint32(__minor(NEWDEV, dev))
543
}
544
545
/*
546
 * Expose the ioctl function
547
 */
548
549
//sys	ioctlRet(fd int, req int, arg uintptr) (ret int, err error) = libc.ioctl
550
//sys	ioctlPtrRet(fd int, req int, arg unsafe.Pointer) (ret int, err error) = libc.ioctl
551
552
func ioctl(fd int, req int, arg uintptr) (err error) {
553
	_, err = ioctlRet(fd, req, arg)
554
	return err
555
}
556
557
func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
558
	_, err = ioctlPtrRet(fd, req, arg)
559
	return err
560
}
561
562
func IoctlSetTermio(fd int, req int, value *Termio) error {
563
	return ioctlPtr(fd, req, unsafe.Pointer(value))
564
}
565
566
func IoctlGetTermio(fd int, req int) (*Termio, error) {
567
	var value Termio
568
	err := ioctlPtr(fd, req, unsafe.Pointer(&value))
569
	return &value, err
570
}
571
572
//sys	poll(fds *PollFd, nfds int, timeout int) (n int, err error)
573
574
func Poll(fds []PollFd, timeout int) (n int, err error) {
575
	if len(fds) == 0 {
576
		return poll(nil, 0, timeout)
577
	}
578
	return poll(&fds[0], len(fds), timeout)
579
}
580
581
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
582
	if raceenabled {
583
		raceReleaseMerge(unsafe.Pointer(&ioSync))
584
	}
585
	return sendfile(outfd, infd, offset, count)
586
}
587
588
/*
589
 * Exposed directly
590
 */
591
//sys	Access(path string, mode uint32) (err error)
592
//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
593
//sys	Chdir(path string) (err error)
594
//sys	Chmod(path string, mode uint32) (err error)
595
//sys	Chown(path string, uid int, gid int) (err error)
596
//sys	Chroot(path string) (err error)
597
//sys	ClockGettime(clockid int32, time *Timespec) (err error)
598
//sys	Close(fd int) (err error)
599
//sys	Creat(path string, mode uint32) (fd int, err error)
600
//sys	Dup(fd int) (nfd int, err error)
601
//sys	Dup2(oldfd int, newfd int) (err error)
602
//sys	Exit(code int)
603
//sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
604
//sys	Fchdir(fd int) (err error)
605
//sys	Fchmod(fd int, mode uint32) (err error)
606
//sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
607
//sys	Fchown(fd int, uid int, gid int) (err error)
608
//sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
609
//sys	Fdatasync(fd int) (err error)
610
//sys	Flock(fd int, how int) (err error)
611
//sys	Fpathconf(fd int, name int) (val int, err error)
612
//sys	Fstat(fd int, stat *Stat_t) (err error)
613
//sys	Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
614
//sys	Fstatvfs(fd int, vfsstat *Statvfs_t) (err error)
615
//sys	Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
616
//sysnb	Getgid() (gid int)
617
//sysnb	Getpid() (pid int)
618
//sysnb	Getpgid(pid int) (pgid int, err error)
619
//sysnb	Getpgrp() (pgid int, err error)
620
//sys	Geteuid() (euid int)
621
//sys	Getegid() (egid int)
622
//sys	Getppid() (ppid int)
623
//sys	Getpriority(which int, who int) (n int, err error)
624
//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
625
//sysnb	Getrusage(who int, rusage *Rusage) (err error)
626
//sysnb	Getsid(pid int) (sid int, err error)
627
//sysnb	Gettimeofday(tv *Timeval) (err error)
628
//sysnb	Getuid() (uid int)
629
//sys	Kill(pid int, signum syscall.Signal) (err error)
630
//sys	Lchown(path string, uid int, gid int) (err error)
631
//sys	Link(path string, link string) (err error)
632
//sys	Listen(s int, backlog int) (err error) = libsocket.__xnet_listen
633
//sys	Lstat(path string, stat *Stat_t) (err error)
634
//sys	Madvise(b []byte, advice int) (err error)
635
//sys	Mkdir(path string, mode uint32) (err error)
636
//sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
637
//sys	Mkfifo(path string, mode uint32) (err error)
638
//sys	Mkfifoat(dirfd int, path string, mode uint32) (err error)
639
//sys	Mknod(path string, mode uint32, dev int) (err error)
640
//sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
641
//sys	Mlock(b []byte) (err error)
642
//sys	Mlockall(flags int) (err error)
643
//sys	Mprotect(b []byte, prot int) (err error)
644
//sys	Msync(b []byte, flags int) (err error)
645
//sys	Munlock(b []byte) (err error)
646
//sys	Munlockall() (err error)
647
//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
648
//sys	Open(path string, mode int, perm uint32) (fd int, err error)
649
//sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
650
//sys	Pathconf(path string, name int) (val int, err error)
651
//sys	Pause() (err error)
652
//sys	pread(fd int, p []byte, offset int64) (n int, err error)
653
//sys	pwrite(fd int, p []byte, offset int64) (n int, err error)
654
//sys	read(fd int, p []byte) (n int, err error)
655
//sys	Readlink(path string, buf []byte) (n int, err error)
656
//sys	Rename(from string, to string) (err error)
657
//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
658
//sys	Rmdir(path string) (err error)
659
//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
660
//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
661
//sysnb	Setegid(egid int) (err error)
662
//sysnb	Seteuid(euid int) (err error)
663
//sysnb	Setgid(gid int) (err error)
664
//sys	Sethostname(p []byte) (err error)
665
//sysnb	Setpgid(pid int, pgid int) (err error)
666
//sys	Setpriority(which int, who int, prio int) (err error)
667
//sysnb	Setregid(rgid int, egid int) (err error)
668
//sysnb	Setreuid(ruid int, euid int) (err error)
669
//sysnb	Setsid() (pid int, err error)
670
//sysnb	Setuid(uid int) (err error)
671
//sys	Shutdown(s int, how int) (err error) = libsocket.shutdown
672
//sys	Stat(path string, stat *Stat_t) (err error)
673
//sys	Statvfs(path string, vfsstat *Statvfs_t) (err error)
674
//sys	Symlink(path string, link string) (err error)
675
//sys	Sync() (err error)
676
//sys	Sysconf(which int) (n int64, err error)
677
//sysnb	Times(tms *Tms) (ticks uintptr, err error)
678
//sys	Truncate(path string, length int64) (err error)
679
//sys	Fsync(fd int) (err error)
680
//sys	Ftruncate(fd int, length int64) (err error)
681
//sys	Umask(mask int) (oldmask int)
682
//sysnb	Uname(buf *Utsname) (err error)
683
//sys	Unmount(target string, flags int) (err error) = libc.umount
684
//sys	Unlink(path string) (err error)
685
//sys	Unlinkat(dirfd int, path string, flags int) (err error)
686
//sys	Ustat(dev int, ubuf *Ustat_t) (err error)
687
//sys	Utime(path string, buf *Utimbuf) (err error)
688
//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
689
//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
690
//sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
691
//sys	munmap(addr uintptr, length uintptr) (err error)
692
//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
693
//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
694
//sys	socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
695
//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
696
//sys	write(fd int, p []byte) (n int, err error)
697
//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
698
//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
699
//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
700
//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
701
702
// Event Ports
703
704
type fileObjCookie struct {
705
	fobj   *fileObj
706
	cookie interface{}
707
}
708
709
// EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
710
type EventPort struct {
711
	port  int
712
	mu    sync.Mutex
713
	fds   map[uintptr]*fileObjCookie
714
	paths map[string]*fileObjCookie
715
	// The user cookie presents an interesting challenge from a memory management perspective.
716
	// There are two paths by which we can discover that it is no longer in use:
717
	// 1. The user calls port_dissociate before any events fire
718
	// 2. An event fires and we return it to the user
719
	// The tricky situation is if the event has fired in the kernel but
720
	// the user hasn't requested/received it yet.
721
	// If the user wants to port_dissociate before the event has been processed,
722
	// we should handle things gracefully. To do so, we need to keep an extra
723
	// reference to the cookie around until the event is processed
724
	// thus the otherwise seemingly extraneous "cookies" map
725
	// The key of this map is a pointer to the corresponding fCookie
726
	cookies map[*fileObjCookie]struct{}
727
}
728
729
// PortEvent is an abstraction of the port_event C struct.
730
// Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
731
// to see if Path or Fd was the event source. The other will be
732
// uninitialized.
733
type PortEvent struct {
734
	Cookie interface{}
735
	Events int32
736
	Fd     uintptr
737
	Path   string
738
	Source uint16
739
	fobj   *fileObj
740
}
741
742
// NewEventPort creates a new EventPort including the
743
// underlying call to port_create(3c).
744
func NewEventPort() (*EventPort, error) {
745
	port, err := port_create()
746
	if err != nil {
747
		return nil, err
748
	}
749
	e := &EventPort{
750
		port:    port,
751
		fds:     make(map[uintptr]*fileObjCookie),
752
		paths:   make(map[string]*fileObjCookie),
753
		cookies: make(map[*fileObjCookie]struct{}),
754
	}
755
	return e, nil
756
}
757
758
//sys	port_create() (n int, err error)
759
//sys	port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error)
760
//sys	port_dissociate(port int, source int, object uintptr) (n int, err error)
761
//sys	port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error)
762
//sys	port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error)
763
764
// Close closes the event port.
765
func (e *EventPort) Close() error {
766
	e.mu.Lock()
767
	defer e.mu.Unlock()
768
	err := Close(e.port)
769
	if err != nil {
770
		return err
771
	}
772
	e.fds = nil
773
	e.paths = nil
774
	e.cookies = nil
775
	return nil
776
}
777
778
// PathIsWatched checks to see if path is associated with this EventPort.
779
func (e *EventPort) PathIsWatched(path string) bool {
780
	e.mu.Lock()
781
	defer e.mu.Unlock()
782
	_, found := e.paths[path]
783
	return found
784
}
785
786
// FdIsWatched checks to see if fd is associated with this EventPort.
787
func (e *EventPort) FdIsWatched(fd uintptr) bool {
788
	e.mu.Lock()
789
	defer e.mu.Unlock()
790
	_, found := e.fds[fd]
791
	return found
792
}
793
794
// AssociatePath wraps port_associate(3c) for a filesystem path including
795
// creating the necessary file_obj from the provided stat information.
796
func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
797
	e.mu.Lock()
798
	defer e.mu.Unlock()
799
	if _, found := e.paths[path]; found {
800
		return fmt.Errorf("%v is already associated with this Event Port", path)
801
	}
802
	fCookie, err := createFileObjCookie(path, stat, cookie)
803
	if err != nil {
804
		return err
805
	}
806
	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fCookie.fobj)), events, (*byte)(unsafe.Pointer(fCookie)))
807
	if err != nil {
808
		return err
809
	}
810
	e.paths[path] = fCookie
811
	e.cookies[fCookie] = struct{}{}
812
	return nil
813
}
814
815
// DissociatePath wraps port_dissociate(3c) for a filesystem path.
816
func (e *EventPort) DissociatePath(path string) error {
817
	e.mu.Lock()
818
	defer e.mu.Unlock()
819
	f, ok := e.paths[path]
820
	if !ok {
821
		return fmt.Errorf("%v is not associated with this Event Port", path)
822
	}
823
	_, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
824
	// If the path is no longer associated with this event port (ENOENT)
825
	// we should delete it from our map. We can still return ENOENT to the caller.
826
	// But we need to save the cookie
827
	if err != nil && err != ENOENT {
828
		return err
829
	}
830
	if err == nil {
831
		// dissociate was successful, safe to delete the cookie
832
		fCookie := e.paths[path]
833
		delete(e.cookies, fCookie)
834
	}
835
	delete(e.paths, path)
836
	return err
837
}
838
839
// AssociateFd wraps calls to port_associate(3c) on file descriptors.
840
func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
841
	e.mu.Lock()
842
	defer e.mu.Unlock()
843
	if _, found := e.fds[fd]; found {
844
		return fmt.Errorf("%v is already associated with this Event Port", fd)
845
	}
846
	fCookie, err := createFileObjCookie("", nil, cookie)
847
	if err != nil {
848
		return err
849
	}
850
	_, err = port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(fCookie)))
851
	if err != nil {
852
		return err
853
	}
854
	e.fds[fd] = fCookie
855
	e.cookies[fCookie] = struct{}{}
856
	return nil
857
}
858
859
// DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
860
func (e *EventPort) DissociateFd(fd uintptr) error {
861
	e.mu.Lock()
862
	defer e.mu.Unlock()
863
	_, ok := e.fds[fd]
864
	if !ok {
865
		return fmt.Errorf("%v is not associated with this Event Port", fd)
866
	}
867
	_, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
868
	if err != nil && err != ENOENT {
869
		return err
870
	}
871
	if err == nil {
872
		// dissociate was successful, safe to delete the cookie
873
		fCookie := e.fds[fd]
874
		delete(e.cookies, fCookie)
875
	}
876
	delete(e.fds, fd)
877
	return err
878
}
879
880
func createFileObjCookie(name string, stat os.FileInfo, cookie interface{}) (*fileObjCookie, error) {
881
	fCookie := new(fileObjCookie)
882
	fCookie.cookie = cookie
883
	if name != "" && stat != nil {
884
		fCookie.fobj = new(fileObj)
885
		bs, err := ByteSliceFromString(name)
886
		if err != nil {
887
			return nil, err
888
		}
889
		fCookie.fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
890
		s := stat.Sys().(*syscall.Stat_t)
891
		fCookie.fobj.Atim.Sec = s.Atim.Sec
892
		fCookie.fobj.Atim.Nsec = s.Atim.Nsec
893
		fCookie.fobj.Mtim.Sec = s.Mtim.Sec
894
		fCookie.fobj.Mtim.Nsec = s.Mtim.Nsec
895
		fCookie.fobj.Ctim.Sec = s.Ctim.Sec
896
		fCookie.fobj.Ctim.Nsec = s.Ctim.Nsec
897
	}
898
	return fCookie, nil
899
}
900
901
// GetOne wraps port_get(3c) and returns a single PortEvent.
902
func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
903
	pe := new(portEvent)
904
	_, err := port_get(e.port, pe, t)
905
	if err != nil {
906
		return nil, err
907
	}
908
	p := new(PortEvent)
909
	e.mu.Lock()
910
	defer e.mu.Unlock()
911
	err = e.peIntToExt(pe, p)
912
	if err != nil {
913
		return nil, err
914
	}
915
	return p, nil
916
}
917
918
// peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
919
// NOTE: Always call this function while holding the e.mu mutex
920
func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) error {
921
	if e.cookies == nil {
922
		return fmt.Errorf("this EventPort is already closed")
923
	}
924
	peExt.Events = peInt.Events
925
	peExt.Source = peInt.Source
926
	fCookie := (*fileObjCookie)(unsafe.Pointer(peInt.User))
927
	_, found := e.cookies[fCookie]
928
929
	if !found {
930
		panic("unexpected event port address; may be due to kernel bug; see https://go.dev/issue/54254")
931
	}
932
	peExt.Cookie = fCookie.cookie
933
	delete(e.cookies, fCookie)
934
935
	switch peInt.Source {
936
	case PORT_SOURCE_FD:
937
		peExt.Fd = uintptr(peInt.Object)
938
		// Only remove the fds entry if it exists and this cookie matches
939
		if fobj, ok := e.fds[peExt.Fd]; ok {
940
			if fobj == fCookie {
941
				delete(e.fds, peExt.Fd)
942
			}
943
		}
944
	case PORT_SOURCE_FILE:
945
		peExt.fobj = fCookie.fobj
946
		peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
947
		// Only remove the paths entry if it exists and this cookie matches
948
		if fobj, ok := e.paths[peExt.Path]; ok {
949
			if fobj == fCookie {
950
				delete(e.paths, peExt.Path)
951
			}
952
		}
953
	}
954
	return nil
955
}
956
957
// Pending wraps port_getn(3c) and returns how many events are pending.
958
func (e *EventPort) Pending() (int, error) {
959
	var n uint32 = 0
960
	_, err := port_getn(e.port, nil, 0, &n, nil)
961
	return int(n), err
962
}
963
964
// Get wraps port_getn(3c) and fills a slice of PortEvent.
965
// It will block until either min events have been received
966
// or the timeout has been exceeded. It will return how many
967
// events were actually received along with any error information.
968
func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
969
	if min == 0 {
970
		return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
971
	}
972
	if len(s) < min {
973
		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
974
	}
975
	got := uint32(min)
976
	max := uint32(len(s))
977
	var err error
978
	ps := make([]portEvent, max)
979
	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
980
	// got will be trustworthy with ETIME, but not any other error.
981
	if err != nil && err != ETIME {
982
		return 0, err
983
	}
984
	e.mu.Lock()
985
	defer e.mu.Unlock()
986
	valid := 0
987
	for i := 0; i < int(got); i++ {
988
		err2 := e.peIntToExt(&ps[i], &s[i])
989
		if err2 != nil {
990
			if valid == 0 && err == nil {
991
				// If err2 is the only error and there are no valid events
992
				// to return, return it to the caller.
993
				err = err2
994
			}
995
			break
996
		}
997
		valid = i + 1
998
	}
999
	return valid, err
1000
}
1001
1002
//sys	putmsg(fd int, clptr *strbuf, dataptr *strbuf, flags int) (err error)
1003
1004
func Putmsg(fd int, cl []byte, data []byte, flags int) (err error) {
1005
	var clp, datap *strbuf
1006
	if len(cl) > 0 {
1007
		clp = &strbuf{
1008
			Len: int32(len(cl)),
1009
			Buf: (*int8)(unsafe.Pointer(&cl[0])),
1010
		}
1011
	}
1012
	if len(data) > 0 {
1013
		datap = &strbuf{
1014
			Len: int32(len(data)),
1015
			Buf: (*int8)(unsafe.Pointer(&data[0])),
1016
		}
1017
	}
1018
	return putmsg(fd, clp, datap, flags)
1019
}
1020
1021
//sys	getmsg(fd int, clptr *strbuf, dataptr *strbuf, flags *int) (err error)
1022
1023
func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags int, err error) {
1024
	var clp, datap *strbuf
1025
	if len(cl) > 0 {
1026
		clp = &strbuf{
1027
			Maxlen: int32(len(cl)),
1028
			Buf:    (*int8)(unsafe.Pointer(&cl[0])),
1029
		}
1030
	}
1031
	if len(data) > 0 {
1032
		datap = &strbuf{
1033
			Maxlen: int32(len(data)),
1034
			Buf:    (*int8)(unsafe.Pointer(&data[0])),
1035
		}
1036
	}
1037
1038
	if err = getmsg(fd, clp, datap, &flags); err != nil {
1039
		return nil, nil, 0, err
1040
	}
1041
1042
	if len(cl) > 0 {
1043
		retCl = cl[:clp.Len]
1044
	}
1045
	if len(data) > 0 {
1046
		retData = data[:datap.Len]
1047
	}
1048
	return retCl, retData, flags, nil
1049
}
1050
1051
func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
1052
	return ioctlRet(fd, req, uintptr(arg))
1053
}
1054
1055
// Lifreq Helpers
1056
1057
func (l *Lifreq) SetName(name string) error {
1058
	if len(name) >= len(l.Name) {
1059
		return fmt.Errorf("name cannot be more than %d characters", len(l.Name)-1)
1060
	}
1061
	for i := range name {
1062
		l.Name[i] = int8(name[i])
1063
	}
1064
	return nil
1065
}
1066
1067
func (l *Lifreq) SetLifruInt(d int) {
1068
	*(*int)(unsafe.Pointer(&l.Lifru[0])) = d
1069
}
1070
1071
func (l *Lifreq) GetLifruInt() int {
1072
	return *(*int)(unsafe.Pointer(&l.Lifru[0]))
1073
}
1074
1075
func (l *Lifreq) SetLifruUint(d uint) {
1076
	*(*uint)(unsafe.Pointer(&l.Lifru[0])) = d
1077
}
1078
1079
func (l *Lifreq) GetLifruUint() uint {
1080
	return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
1081
}
1082
1083
func IoctlLifreq(fd int, req int, l *Lifreq) error {
1084
	return ioctlPtr(fd, req, unsafe.Pointer(l))
1085
}
1086
1087
// Strioctl Helpers
1088
1089
func (s *Strioctl) SetInt(i int) {
1090
	s.Len = int32(unsafe.Sizeof(i))
1091
	s.Dp = (*int8)(unsafe.Pointer(&i))
1092
}
1093
1094
func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
1095
	return ioctlPtrRet(fd, req, unsafe.Pointer(s))
1096
}
1097
1098
// Ucred Helpers
1099
// See ucred(3c) and getpeerucred(3c)
1100
1101
//sys	getpeerucred(fd uintptr, ucred *uintptr) (err error)
1102
//sys	ucredFree(ucred uintptr) = ucred_free
1103
//sys	ucredGet(pid int) (ucred uintptr, err error) = ucred_get
1104
//sys	ucredGeteuid(ucred uintptr) (uid int) = ucred_geteuid
1105
//sys	ucredGetegid(ucred uintptr) (gid int) = ucred_getegid
1106
//sys	ucredGetruid(ucred uintptr) (uid int) = ucred_getruid
1107
//sys	ucredGetrgid(ucred uintptr) (gid int) = ucred_getrgid
1108
//sys	ucredGetsuid(ucred uintptr) (uid int) = ucred_getsuid
1109
//sys	ucredGetsgid(ucred uintptr) (gid int) = ucred_getsgid
1110
//sys	ucredGetpid(ucred uintptr) (pid int) = ucred_getpid
1111
1112
// Ucred is an opaque struct that holds user credentials.
1113
type Ucred struct {
1114
	ucred uintptr
1115
}
1116
1117
// We need to ensure that ucredFree is called on the underlying ucred
1118
// when the Ucred is garbage collected.
1119
func ucredFinalizer(u *Ucred) {
1120
	ucredFree(u.ucred)
1121
}
1122
1123
func GetPeerUcred(fd uintptr) (*Ucred, error) {
1124
	var ucred uintptr
1125
	err := getpeerucred(fd, &ucred)
1126
	if err != nil {
1127
		return nil, err
1128
	}
1129
	result := &Ucred{
1130
		ucred: ucred,
1131
	}
1132
	// set the finalizer on the result so that the ucred will be freed
1133
	runtime.SetFinalizer(result, ucredFinalizer)
1134
	return result, nil
1135
}
1136
1137
func UcredGet(pid int) (*Ucred, error) {
1138
	ucred, err := ucredGet(pid)
1139
	if err != nil {
1140
		return nil, err
1141
	}
1142
	result := &Ucred{
1143
		ucred: ucred,
1144
	}
1145
	// set the finalizer on the result so that the ucred will be freed
1146
	runtime.SetFinalizer(result, ucredFinalizer)
1147
	return result, nil
1148
}
1149
1150
func (u *Ucred) Geteuid() int {
1151
	defer runtime.KeepAlive(u)
1152
	return ucredGeteuid(u.ucred)
1153
}
1154
1155
func (u *Ucred) Getruid() int {
1156
	defer runtime.KeepAlive(u)
1157
	return ucredGetruid(u.ucred)
1158
}
1159
1160
func (u *Ucred) Getsuid() int {
1161
	defer runtime.KeepAlive(u)
1162
	return ucredGetsuid(u.ucred)
1163
}
1164
1165
func (u *Ucred) Getegid() int {
1166
	defer runtime.KeepAlive(u)
1167
	return ucredGetegid(u.ucred)
1168
}
1169
1170
func (u *Ucred) Getrgid() int {
1171
	defer runtime.KeepAlive(u)
1172
	return ucredGetrgid(u.ucred)
1173
}
1174
1175
func (u *Ucred) Getsgid() int {
1176
	defer runtime.KeepAlive(u)
1177
	return ucredGetsgid(u.ucred)
1178
}
1179
1180
func (u *Ucred) Getpid() int {
1181
	defer runtime.KeepAlive(u)
1182
	return ucredGetpid(u.ucred)
1183
}