cubefs

Форк
0
/x
/
syscall_solaris.go 
1135 строк · 31.8 Кб
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] == '@' {
132
		sa.raw.Path[0] = 0
133
		// Don't count trailing NUL for abstract address.
134
		sl--
135
	}
136

137
	return unsafe.Pointer(&sa.raw), sl, nil
138
}
139

140
//sys	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname
141

142
func Getsockname(fd int) (sa Sockaddr, err error) {
143
	var rsa RawSockaddrAny
144
	var len _Socklen = SizeofSockaddrAny
145
	if err = getsockname(fd, &rsa, &len); err != nil {
146
		return
147
	}
148
	return anyToSockaddr(fd, &rsa)
149
}
150

151
// GetsockoptString returns the string value of the socket option opt for the
152
// socket associated with fd at the given socket level.
153
func GetsockoptString(fd, level, opt int) (string, error) {
154
	buf := make([]byte, 256)
155
	vallen := _Socklen(len(buf))
156
	err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
157
	if err != nil {
158
		return "", err
159
	}
160
	return string(buf[:vallen-1]), nil
161
}
162

163
const ImplementsGetwd = true
164

165
//sys	Getcwd(buf []byte) (n int, err error)
166

167
func Getwd() (wd string, err error) {
168
	var buf [PathMax]byte
169
	// Getcwd will return an error if it failed for any reason.
170
	_, err = Getcwd(buf[0:])
171
	if err != nil {
172
		return "", err
173
	}
174
	n := clen(buf[:])
175
	if n < 1 {
176
		return "", EINVAL
177
	}
178
	return string(buf[:n]), nil
179
}
180

181
/*
182
 * Wrapped
183
 */
184

185
//sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
186
//sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
187

188
func Getgroups() (gids []int, err error) {
189
	n, err := getgroups(0, nil)
190
	// Check for error and sanity check group count. Newer versions of
191
	// Solaris allow up to 1024 (NGROUPS_MAX).
192
	if n < 0 || n > 1024 {
193
		if err != nil {
194
			return nil, err
195
		}
196
		return nil, EINVAL
197
	} else if n == 0 {
198
		return nil, nil
199
	}
200

201
	a := make([]_Gid_t, n)
202
	n, err = getgroups(n, &a[0])
203
	if n == -1 {
204
		return nil, err
205
	}
206
	gids = make([]int, n)
207
	for i, v := range a[0:n] {
208
		gids[i] = int(v)
209
	}
210
	return
211
}
212

213
func Setgroups(gids []int) (err error) {
214
	if len(gids) == 0 {
215
		return setgroups(0, nil)
216
	}
217

218
	a := make([]_Gid_t, len(gids))
219
	for i, v := range gids {
220
		a[i] = _Gid_t(v)
221
	}
222
	return setgroups(len(a), &a[0])
223
}
224

225
// ReadDirent reads directory entries from fd and writes them into buf.
226
func ReadDirent(fd int, buf []byte) (n int, err error) {
227
	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
228
	// TODO(rsc): Can we use a single global basep for all calls?
229
	return Getdents(fd, buf, new(uintptr))
230
}
231

232
// Wait status is 7 bits at bottom, either 0 (exited),
233
// 0x7F (stopped), or a signal number that caused an exit.
234
// The 0x80 bit is whether there was a core dump.
235
// An extra number (exit code, signal causing a stop)
236
// is in the high bits.
237

238
type WaitStatus uint32
239

240
const (
241
	mask  = 0x7F
242
	core  = 0x80
243
	shift = 8
244

245
	exited  = 0
246
	stopped = 0x7F
247
)
248

249
func (w WaitStatus) Exited() bool { return w&mask == exited }
250

251
func (w WaitStatus) ExitStatus() int {
252
	if w&mask != exited {
253
		return -1
254
	}
255
	return int(w >> shift)
256
}
257

258
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
259

260
func (w WaitStatus) Signal() syscall.Signal {
261
	sig := syscall.Signal(w & mask)
262
	if sig == stopped || sig == 0 {
263
		return -1
264
	}
265
	return sig
266
}
267

268
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
269

270
func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
271

272
func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
273

274
func (w WaitStatus) StopSignal() syscall.Signal {
275
	if !w.Stopped() {
276
		return -1
277
	}
278
	return syscall.Signal(w>>shift) & 0xFF
279
}
280

281
func (w WaitStatus) TrapCause() int { return -1 }
282

283
//sys	wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error)
284

285
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
286
	var status _C_int
287
	rpid, err := wait4(int32(pid), &status, options, rusage)
288
	wpid := int(rpid)
289
	if wpid == -1 {
290
		return wpid, err
291
	}
292
	if wstatus != nil {
293
		*wstatus = WaitStatus(status)
294
	}
295
	return wpid, nil
296
}
297

298
//sys	gethostname(buf []byte) (n int, err error)
299

300
func Gethostname() (name string, err error) {
301
	var buf [MaxHostNameLen]byte
302
	n, err := gethostname(buf[:])
303
	if n != 0 {
304
		return "", err
305
	}
306
	n = clen(buf[:])
307
	if n < 1 {
308
		return "", EFAULT
309
	}
310
	return string(buf[:n]), nil
311
}
312

313
//sys	utimes(path string, times *[2]Timeval) (err error)
314

315
func Utimes(path string, tv []Timeval) (err error) {
316
	if tv == nil {
317
		return utimes(path, nil)
318
	}
319
	if len(tv) != 2 {
320
		return EINVAL
321
	}
322
	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
323
}
324

325
//sys	utimensat(fd int, path string, times *[2]Timespec, flag int) (err error)
326

327
func UtimesNano(path string, ts []Timespec) error {
328
	if ts == nil {
329
		return utimensat(AT_FDCWD, path, nil, 0)
330
	}
331
	if len(ts) != 2 {
332
		return EINVAL
333
	}
334
	return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
335
}
336

337
func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
338
	if ts == nil {
339
		return utimensat(dirfd, path, nil, flags)
340
	}
341
	if len(ts) != 2 {
342
		return EINVAL
343
	}
344
	return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
345
}
346

347
//sys	fcntl(fd int, cmd int, arg int) (val int, err error)
348

349
// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
350
func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
351
	valptr, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
352
	var err error
353
	if errno != 0 {
354
		err = errno
355
	}
356
	return int(valptr), err
357
}
358

359
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
360
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
361
	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
362
	if e1 != 0 {
363
		return e1
364
	}
365
	return nil
366
}
367

368
//sys	futimesat(fildes int, path *byte, times *[2]Timeval) (err error)
369

370
func Futimesat(dirfd int, path string, tv []Timeval) error {
371
	pathp, err := BytePtrFromString(path)
372
	if err != nil {
373
		return err
374
	}
375
	if tv == nil {
376
		return futimesat(dirfd, pathp, nil)
377
	}
378
	if len(tv) != 2 {
379
		return EINVAL
380
	}
381
	return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
382
}
383

384
// Solaris doesn't have an futimes function because it allows NULL to be
385
// specified as the path for futimesat. However, Go doesn't like
386
// NULL-style string interfaces, so this simple wrapper is provided.
387
func Futimes(fd int, tv []Timeval) error {
388
	if tv == nil {
389
		return futimesat(fd, nil, nil)
390
	}
391
	if len(tv) != 2 {
392
		return EINVAL
393
	}
394
	return futimesat(fd, nil, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
395
}
396

397
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
398
	switch rsa.Addr.Family {
399
	case AF_UNIX:
400
		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
401
		sa := new(SockaddrUnix)
402
		// Assume path ends at NUL.
403
		// This is not technically the Solaris semantics for
404
		// abstract Unix domain sockets -- they are supposed
405
		// to be uninterpreted fixed-size binary blobs -- but
406
		// everyone uses this convention.
407
		n := 0
408
		for n < len(pp.Path) && pp.Path[n] != 0 {
409
			n++
410
		}
411
		sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
412
		return sa, nil
413

414
	case AF_INET:
415
		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
416
		sa := new(SockaddrInet4)
417
		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
418
		sa.Port = int(p[0])<<8 + int(p[1])
419
		sa.Addr = pp.Addr
420
		return sa, nil
421

422
	case AF_INET6:
423
		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
424
		sa := new(SockaddrInet6)
425
		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
426
		sa.Port = int(p[0])<<8 + int(p[1])
427
		sa.ZoneId = pp.Scope_id
428
		sa.Addr = pp.Addr
429
		return sa, nil
430
	}
431
	return nil, EAFNOSUPPORT
432
}
433

434
//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept
435

436
func Accept(fd int) (nfd int, sa Sockaddr, err error) {
437
	var rsa RawSockaddrAny
438
	var len _Socklen = SizeofSockaddrAny
439
	nfd, err = accept(fd, &rsa, &len)
440
	if nfd == -1 {
441
		return
442
	}
443
	sa, err = anyToSockaddr(fd, &rsa)
444
	if err != nil {
445
		Close(nfd)
446
		nfd = 0
447
	}
448
	return
449
}
450

451
//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
452

453
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
454
	var msg Msghdr
455
	msg.Name = (*byte)(unsafe.Pointer(rsa))
456
	msg.Namelen = uint32(SizeofSockaddrAny)
457
	var dummy byte
458
	if len(oob) > 0 {
459
		// receive at least one normal byte
460
		if emptyIovecs(iov) {
461
			var iova [1]Iovec
462
			iova[0].Base = &dummy
463
			iova[0].SetLen(1)
464
			iov = iova[:]
465
		}
466
		msg.Accrightslen = int32(len(oob))
467
	}
468
	if len(iov) > 0 {
469
		msg.Iov = &iov[0]
470
		msg.SetIovlen(len(iov))
471
	}
472
	if n, err = recvmsg(fd, &msg, flags); n == -1 {
473
		return
474
	}
475
	oobn = int(msg.Accrightslen)
476
	return
477
}
478

479
//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
480

481
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
482
	var msg Msghdr
483
	msg.Name = (*byte)(unsafe.Pointer(ptr))
484
	msg.Namelen = uint32(salen)
485
	var dummy byte
486
	var empty bool
487
	if len(oob) > 0 {
488
		// send at least one normal byte
489
		empty = emptyIovecs(iov)
490
		if empty {
491
			var iova [1]Iovec
492
			iova[0].Base = &dummy
493
			iova[0].SetLen(1)
494
			iov = iova[:]
495
		}
496
		msg.Accrightslen = int32(len(oob))
497
	}
498
	if len(iov) > 0 {
499
		msg.Iov = &iov[0]
500
		msg.SetIovlen(len(iov))
501
	}
502
	if n, err = sendmsg(fd, &msg, flags); err != nil {
503
		return 0, err
504
	}
505
	if len(oob) > 0 && empty {
506
		n = 0
507
	}
508
	return n, nil
509
}
510

511
//sys	acct(path *byte) (err error)
512

513
func Acct(path string) (err error) {
514
	if len(path) == 0 {
515
		// Assume caller wants to disable accounting.
516
		return acct(nil)
517
	}
518

519
	pathp, err := BytePtrFromString(path)
520
	if err != nil {
521
		return err
522
	}
523
	return acct(pathp)
524
}
525

526
//sys	__makedev(version int, major uint, minor uint) (val uint64)
527

528
func Mkdev(major, minor uint32) uint64 {
529
	return __makedev(NEWDEV, uint(major), uint(minor))
530
}
531

532
//sys	__major(version int, dev uint64) (val uint)
533

534
func Major(dev uint64) uint32 {
535
	return uint32(__major(NEWDEV, dev))
536
}
537

538
//sys	__minor(version int, dev uint64) (val uint)
539

540
func Minor(dev uint64) uint32 {
541
	return uint32(__minor(NEWDEV, dev))
542
}
543

544
/*
545
 * Expose the ioctl function
546
 */
547

548
//sys	ioctlRet(fd int, req int, arg uintptr) (ret int, err error) = libc.ioctl
549
//sys	ioctlPtrRet(fd int, req int, arg unsafe.Pointer) (ret int, err error) = libc.ioctl
550

551
func ioctl(fd int, req int, arg uintptr) (err error) {
552
	_, err = ioctlRet(fd, req, arg)
553
	return err
554
}
555

556
func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
557
	_, err = ioctlPtrRet(fd, req, arg)
558
	return err
559
}
560

561
func IoctlSetTermio(fd int, req int, value *Termio) error {
562
	return ioctlPtr(fd, req, unsafe.Pointer(value))
563
}
564

565
func IoctlGetTermio(fd int, req int) (*Termio, error) {
566
	var value Termio
567
	err := ioctlPtr(fd, req, unsafe.Pointer(&value))
568
	return &value, err
569
}
570

571
//sys	poll(fds *PollFd, nfds int, timeout int) (n int, err error)
572

573
func Poll(fds []PollFd, timeout int) (n int, err error) {
574
	if len(fds) == 0 {
575
		return poll(nil, 0, timeout)
576
	}
577
	return poll(&fds[0], len(fds), timeout)
578
}
579

580
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
581
	if raceenabled {
582
		raceReleaseMerge(unsafe.Pointer(&ioSync))
583
	}
584
	return sendfile(outfd, infd, offset, count)
585
}
586

587
/*
588
 * Exposed directly
589
 */
590
//sys	Access(path string, mode uint32) (err error)
591
//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
592
//sys	Chdir(path string) (err error)
593
//sys	Chmod(path string, mode uint32) (err error)
594
//sys	Chown(path string, uid int, gid int) (err error)
595
//sys	Chroot(path string) (err error)
596
//sys	ClockGettime(clockid int32, time *Timespec) (err error)
597
//sys	Close(fd int) (err error)
598
//sys	Creat(path string, mode uint32) (fd int, err error)
599
//sys	Dup(fd int) (nfd int, err error)
600
//sys	Dup2(oldfd int, newfd int) (err error)
601
//sys	Exit(code int)
602
//sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
603
//sys	Fchdir(fd int) (err error)
604
//sys	Fchmod(fd int, mode uint32) (err error)
605
//sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
606
//sys	Fchown(fd int, uid int, gid int) (err error)
607
//sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
608
//sys	Fdatasync(fd int) (err error)
609
//sys	Flock(fd int, how int) (err error)
610
//sys	Fpathconf(fd int, name int) (val int, err error)
611
//sys	Fstat(fd int, stat *Stat_t) (err error)
612
//sys	Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
613
//sys	Fstatvfs(fd int, vfsstat *Statvfs_t) (err error)
614
//sys	Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
615
//sysnb	Getgid() (gid int)
616
//sysnb	Getpid() (pid int)
617
//sysnb	Getpgid(pid int) (pgid int, err error)
618
//sysnb	Getpgrp() (pgid int, err error)
619
//sys	Geteuid() (euid int)
620
//sys	Getegid() (egid int)
621
//sys	Getppid() (ppid int)
622
//sys	Getpriority(which int, who int) (n int, err error)
623
//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
624
//sysnb	Getrusage(who int, rusage *Rusage) (err error)
625
//sysnb	Getsid(pid int) (sid int, err error)
626
//sysnb	Gettimeofday(tv *Timeval) (err error)
627
//sysnb	Getuid() (uid int)
628
//sys	Kill(pid int, signum syscall.Signal) (err error)
629
//sys	Lchown(path string, uid int, gid int) (err error)
630
//sys	Link(path string, link string) (err error)
631
//sys	Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten
632
//sys	Lstat(path string, stat *Stat_t) (err error)
633
//sys	Madvise(b []byte, advice int) (err error)
634
//sys	Mkdir(path string, mode uint32) (err error)
635
//sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
636
//sys	Mkfifo(path string, mode uint32) (err error)
637
//sys	Mkfifoat(dirfd int, path string, mode uint32) (err error)
638
//sys	Mknod(path string, mode uint32, dev int) (err error)
639
//sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
640
//sys	Mlock(b []byte) (err error)
641
//sys	Mlockall(flags int) (err error)
642
//sys	Mprotect(b []byte, prot int) (err error)
643
//sys	Msync(b []byte, flags int) (err error)
644
//sys	Munlock(b []byte) (err error)
645
//sys	Munlockall() (err error)
646
//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
647
//sys	Open(path string, mode int, perm uint32) (fd int, err error)
648
//sys	Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
649
//sys	Pathconf(path string, name int) (val int, err error)
650
//sys	Pause() (err error)
651
//sys	pread(fd int, p []byte, offset int64) (n int, err error)
652
//sys	pwrite(fd int, p []byte, offset int64) (n int, err error)
653
//sys	read(fd int, p []byte) (n int, err error)
654
//sys	Readlink(path string, buf []byte) (n int, err error)
655
//sys	Rename(from string, to string) (err error)
656
//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
657
//sys	Rmdir(path string) (err error)
658
//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
659
//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
660
//sysnb	Setegid(egid int) (err error)
661
//sysnb	Seteuid(euid int) (err error)
662
//sysnb	Setgid(gid int) (err error)
663
//sys	Sethostname(p []byte) (err error)
664
//sysnb	Setpgid(pid int, pgid int) (err error)
665
//sys	Setpriority(which int, who int, prio int) (err error)
666
//sysnb	Setregid(rgid int, egid int) (err error)
667
//sysnb	Setreuid(ruid int, euid int) (err error)
668
//sysnb	Setsid() (pid int, err error)
669
//sysnb	Setuid(uid int) (err error)
670
//sys	Shutdown(s int, how int) (err error) = libsocket.shutdown
671
//sys	Stat(path string, stat *Stat_t) (err error)
672
//sys	Statvfs(path string, vfsstat *Statvfs_t) (err error)
673
//sys	Symlink(path string, link string) (err error)
674
//sys	Sync() (err error)
675
//sys	Sysconf(which int) (n int64, err error)
676
//sysnb	Times(tms *Tms) (ticks uintptr, err error)
677
//sys	Truncate(path string, length int64) (err error)
678
//sys	Fsync(fd int) (err error)
679
//sys	Ftruncate(fd int, length int64) (err error)
680
//sys	Umask(mask int) (oldmask int)
681
//sysnb	Uname(buf *Utsname) (err error)
682
//sys	Unmount(target string, flags int) (err error) = libc.umount
683
//sys	Unlink(path string) (err error)
684
//sys	Unlinkat(dirfd int, path string, flags int) (err error)
685
//sys	Ustat(dev int, ubuf *Ustat_t) (err error)
686
//sys	Utime(path string, buf *Utimbuf) (err error)
687
//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
688
//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
689
//sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
690
//sys	munmap(addr uintptr, length uintptr) (err error)
691
//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
692
//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
693
//sys	socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
694
//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
695
//sys	write(fd int, p []byte) (n int, err error)
696
//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
697
//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
698
//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
699
//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
700

701
func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
702
	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
703
	n = int(r0)
704
	if e1 != 0 {
705
		err = e1
706
	}
707
	return
708
}
709

710
func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
711
	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
712
	n = int(r0)
713
	if e1 != 0 {
714
		err = e1
715
	}
716
	return
717
}
718

719
var mapper = &mmapper{
720
	active: make(map[*byte][]byte),
721
	mmap:   mmap,
722
	munmap: munmap,
723
}
724

725
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
726
	return mapper.Mmap(fd, offset, length, prot, flags)
727
}
728

729
func Munmap(b []byte) (err error) {
730
	return mapper.Munmap(b)
731
}
732

733
// Event Ports
734

735
type fileObjCookie struct {
736
	fobj   *fileObj
737
	cookie interface{}
738
}
739

740
// EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
741
type EventPort struct {
742
	port  int
743
	mu    sync.Mutex
744
	fds   map[uintptr]*fileObjCookie
745
	paths map[string]*fileObjCookie
746
	// The user cookie presents an interesting challenge from a memory management perspective.
747
	// There are two paths by which we can discover that it is no longer in use:
748
	// 1. The user calls port_dissociate before any events fire
749
	// 2. An event fires and we return it to the user
750
	// The tricky situation is if the event has fired in the kernel but
751
	// the user hasn't requested/received it yet.
752
	// If the user wants to port_dissociate before the event has been processed,
753
	// we should handle things gracefully. To do so, we need to keep an extra
754
	// reference to the cookie around until the event is processed
755
	// thus the otherwise seemingly extraneous "cookies" map
756
	// The key of this map is a pointer to the corresponding fCookie
757
	cookies map[*fileObjCookie]struct{}
758
}
759

760
// PortEvent is an abstraction of the port_event C struct.
761
// Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
762
// to see if Path or Fd was the event source. The other will be
763
// uninitialized.
764
type PortEvent struct {
765
	Cookie interface{}
766
	Events int32
767
	Fd     uintptr
768
	Path   string
769
	Source uint16
770
	fobj   *fileObj
771
}
772

773
// NewEventPort creates a new EventPort including the
774
// underlying call to port_create(3c).
775
func NewEventPort() (*EventPort, error) {
776
	port, err := port_create()
777
	if err != nil {
778
		return nil, err
779
	}
780
	e := &EventPort{
781
		port:    port,
782
		fds:     make(map[uintptr]*fileObjCookie),
783
		paths:   make(map[string]*fileObjCookie),
784
		cookies: make(map[*fileObjCookie]struct{}),
785
	}
786
	return e, nil
787
}
788

789
//sys	port_create() (n int, err error)
790
//sys	port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error)
791
//sys	port_dissociate(port int, source int, object uintptr) (n int, err error)
792
//sys	port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error)
793
//sys	port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error)
794

795
// Close closes the event port.
796
func (e *EventPort) Close() error {
797
	e.mu.Lock()
798
	defer e.mu.Unlock()
799
	err := Close(e.port)
800
	if err != nil {
801
		return err
802
	}
803
	e.fds = nil
804
	e.paths = nil
805
	e.cookies = nil
806
	return nil
807
}
808

809
// PathIsWatched checks to see if path is associated with this EventPort.
810
func (e *EventPort) PathIsWatched(path string) bool {
811
	e.mu.Lock()
812
	defer e.mu.Unlock()
813
	_, found := e.paths[path]
814
	return found
815
}
816

817
// FdIsWatched checks to see if fd is associated with this EventPort.
818
func (e *EventPort) FdIsWatched(fd uintptr) bool {
819
	e.mu.Lock()
820
	defer e.mu.Unlock()
821
	_, found := e.fds[fd]
822
	return found
823
}
824

825
// AssociatePath wraps port_associate(3c) for a filesystem path including
826
// creating the necessary file_obj from the provided stat information.
827
func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
828
	e.mu.Lock()
829
	defer e.mu.Unlock()
830
	if _, found := e.paths[path]; found {
831
		return fmt.Errorf("%v is already associated with this Event Port", path)
832
	}
833
	fCookie, err := createFileObjCookie(path, stat, cookie)
834
	if err != nil {
835
		return err
836
	}
837
	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fCookie.fobj)), events, (*byte)(unsafe.Pointer(fCookie)))
838
	if err != nil {
839
		return err
840
	}
841
	e.paths[path] = fCookie
842
	e.cookies[fCookie] = struct{}{}
843
	return nil
844
}
845

846
// DissociatePath wraps port_dissociate(3c) for a filesystem path.
847
func (e *EventPort) DissociatePath(path string) error {
848
	e.mu.Lock()
849
	defer e.mu.Unlock()
850
	f, ok := e.paths[path]
851
	if !ok {
852
		return fmt.Errorf("%v is not associated with this Event Port", path)
853
	}
854
	_, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
855
	// If the path is no longer associated with this event port (ENOENT)
856
	// we should delete it from our map. We can still return ENOENT to the caller.
857
	// But we need to save the cookie
858
	if err != nil && err != ENOENT {
859
		return err
860
	}
861
	if err == nil {
862
		// dissociate was successful, safe to delete the cookie
863
		fCookie := e.paths[path]
864
		delete(e.cookies, fCookie)
865
	}
866
	delete(e.paths, path)
867
	return err
868
}
869

870
// AssociateFd wraps calls to port_associate(3c) on file descriptors.
871
func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
872
	e.mu.Lock()
873
	defer e.mu.Unlock()
874
	if _, found := e.fds[fd]; found {
875
		return fmt.Errorf("%v is already associated with this Event Port", fd)
876
	}
877
	fCookie, err := createFileObjCookie("", nil, cookie)
878
	if err != nil {
879
		return err
880
	}
881
	_, err = port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(fCookie)))
882
	if err != nil {
883
		return err
884
	}
885
	e.fds[fd] = fCookie
886
	e.cookies[fCookie] = struct{}{}
887
	return nil
888
}
889

890
// DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
891
func (e *EventPort) DissociateFd(fd uintptr) error {
892
	e.mu.Lock()
893
	defer e.mu.Unlock()
894
	_, ok := e.fds[fd]
895
	if !ok {
896
		return fmt.Errorf("%v is not associated with this Event Port", fd)
897
	}
898
	_, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
899
	if err != nil && err != ENOENT {
900
		return err
901
	}
902
	if err == nil {
903
		// dissociate was successful, safe to delete the cookie
904
		fCookie := e.fds[fd]
905
		delete(e.cookies, fCookie)
906
	}
907
	delete(e.fds, fd)
908
	return err
909
}
910

911
func createFileObjCookie(name string, stat os.FileInfo, cookie interface{}) (*fileObjCookie, error) {
912
	fCookie := new(fileObjCookie)
913
	fCookie.cookie = cookie
914
	if name != "" && stat != nil {
915
		fCookie.fobj = new(fileObj)
916
		bs, err := ByteSliceFromString(name)
917
		if err != nil {
918
			return nil, err
919
		}
920
		fCookie.fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
921
		s := stat.Sys().(*syscall.Stat_t)
922
		fCookie.fobj.Atim.Sec = s.Atim.Sec
923
		fCookie.fobj.Atim.Nsec = s.Atim.Nsec
924
		fCookie.fobj.Mtim.Sec = s.Mtim.Sec
925
		fCookie.fobj.Mtim.Nsec = s.Mtim.Nsec
926
		fCookie.fobj.Ctim.Sec = s.Ctim.Sec
927
		fCookie.fobj.Ctim.Nsec = s.Ctim.Nsec
928
	}
929
	return fCookie, nil
930
}
931

932
// GetOne wraps port_get(3c) and returns a single PortEvent.
933
func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
934
	pe := new(portEvent)
935
	_, err := port_get(e.port, pe, t)
936
	if err != nil {
937
		return nil, err
938
	}
939
	p := new(PortEvent)
940
	e.mu.Lock()
941
	defer e.mu.Unlock()
942
	err = e.peIntToExt(pe, p)
943
	if err != nil {
944
		return nil, err
945
	}
946
	return p, nil
947
}
948

949
// peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
950
// NOTE: Always call this function while holding the e.mu mutex
951
func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) error {
952
	if e.cookies == nil {
953
		return fmt.Errorf("this EventPort is already closed")
954
	}
955
	peExt.Events = peInt.Events
956
	peExt.Source = peInt.Source
957
	fCookie := (*fileObjCookie)(unsafe.Pointer(peInt.User))
958
	_, found := e.cookies[fCookie]
959

960
	if !found {
961
		panic("unexpected event port address; may be due to kernel bug; see https://go.dev/issue/54254")
962
	}
963
	peExt.Cookie = fCookie.cookie
964
	delete(e.cookies, fCookie)
965

966
	switch peInt.Source {
967
	case PORT_SOURCE_FD:
968
		peExt.Fd = uintptr(peInt.Object)
969
		// Only remove the fds entry if it exists and this cookie matches
970
		if fobj, ok := e.fds[peExt.Fd]; ok {
971
			if fobj == fCookie {
972
				delete(e.fds, peExt.Fd)
973
			}
974
		}
975
	case PORT_SOURCE_FILE:
976
		peExt.fobj = fCookie.fobj
977
		peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
978
		// Only remove the paths entry if it exists and this cookie matches
979
		if fobj, ok := e.paths[peExt.Path]; ok {
980
			if fobj == fCookie {
981
				delete(e.paths, peExt.Path)
982
			}
983
		}
984
	}
985
	return nil
986
}
987

988
// Pending wraps port_getn(3c) and returns how many events are pending.
989
func (e *EventPort) Pending() (int, error) {
990
	var n uint32 = 0
991
	_, err := port_getn(e.port, nil, 0, &n, nil)
992
	return int(n), err
993
}
994

995
// Get wraps port_getn(3c) and fills a slice of PortEvent.
996
// It will block until either min events have been received
997
// or the timeout has been exceeded. It will return how many
998
// events were actually received along with any error information.
999
func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
1000
	if min == 0 {
1001
		return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
1002
	}
1003
	if len(s) < min {
1004
		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
1005
	}
1006
	got := uint32(min)
1007
	max := uint32(len(s))
1008
	var err error
1009
	ps := make([]portEvent, max)
1010
	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
1011
	// got will be trustworthy with ETIME, but not any other error.
1012
	if err != nil && err != ETIME {
1013
		return 0, err
1014
	}
1015
	e.mu.Lock()
1016
	defer e.mu.Unlock()
1017
	valid := 0
1018
	for i := 0; i < int(got); i++ {
1019
		err2 := e.peIntToExt(&ps[i], &s[i])
1020
		if err2 != nil {
1021
			if valid == 0 && err == nil {
1022
				// If err2 is the only error and there are no valid events
1023
				// to return, return it to the caller.
1024
				err = err2
1025
			}
1026
			break
1027
		}
1028
		valid = i + 1
1029
	}
1030
	return valid, err
1031
}
1032

1033
//sys	putmsg(fd int, clptr *strbuf, dataptr *strbuf, flags int) (err error)
1034

1035
func Putmsg(fd int, cl []byte, data []byte, flags int) (err error) {
1036
	var clp, datap *strbuf
1037
	if len(cl) > 0 {
1038
		clp = &strbuf{
1039
			Len: int32(len(cl)),
1040
			Buf: (*int8)(unsafe.Pointer(&cl[0])),
1041
		}
1042
	}
1043
	if len(data) > 0 {
1044
		datap = &strbuf{
1045
			Len: int32(len(data)),
1046
			Buf: (*int8)(unsafe.Pointer(&data[0])),
1047
		}
1048
	}
1049
	return putmsg(fd, clp, datap, flags)
1050
}
1051

1052
//sys	getmsg(fd int, clptr *strbuf, dataptr *strbuf, flags *int) (err error)
1053

1054
func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags int, err error) {
1055
	var clp, datap *strbuf
1056
	if len(cl) > 0 {
1057
		clp = &strbuf{
1058
			Maxlen: int32(len(cl)),
1059
			Buf:    (*int8)(unsafe.Pointer(&cl[0])),
1060
		}
1061
	}
1062
	if len(data) > 0 {
1063
		datap = &strbuf{
1064
			Maxlen: int32(len(data)),
1065
			Buf:    (*int8)(unsafe.Pointer(&data[0])),
1066
		}
1067
	}
1068

1069
	if err = getmsg(fd, clp, datap, &flags); err != nil {
1070
		return nil, nil, 0, err
1071
	}
1072

1073
	if len(cl) > 0 {
1074
		retCl = cl[:clp.Len]
1075
	}
1076
	if len(data) > 0 {
1077
		retData = data[:datap.Len]
1078
	}
1079
	return retCl, retData, flags, nil
1080
}
1081

1082
func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
1083
	return ioctlRet(fd, req, uintptr(arg))
1084
}
1085

1086
func IoctlSetString(fd int, req int, val string) error {
1087
	bs := make([]byte, len(val)+1)
1088
	copy(bs[:len(bs)-1], val)
1089
	err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
1090
	runtime.KeepAlive(&bs[0])
1091
	return err
1092
}
1093

1094
// Lifreq Helpers
1095

1096
func (l *Lifreq) SetName(name string) error {
1097
	if len(name) >= len(l.Name) {
1098
		return fmt.Errorf("name cannot be more than %d characters", len(l.Name)-1)
1099
	}
1100
	for i := range name {
1101
		l.Name[i] = int8(name[i])
1102
	}
1103
	return nil
1104
}
1105

1106
func (l *Lifreq) SetLifruInt(d int) {
1107
	*(*int)(unsafe.Pointer(&l.Lifru[0])) = d
1108
}
1109

1110
func (l *Lifreq) GetLifruInt() int {
1111
	return *(*int)(unsafe.Pointer(&l.Lifru[0]))
1112
}
1113

1114
func (l *Lifreq) SetLifruUint(d uint) {
1115
	*(*uint)(unsafe.Pointer(&l.Lifru[0])) = d
1116
}
1117

1118
func (l *Lifreq) GetLifruUint() uint {
1119
	return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
1120
}
1121

1122
func IoctlLifreq(fd int, req int, l *Lifreq) error {
1123
	return ioctlPtr(fd, req, unsafe.Pointer(l))
1124
}
1125

1126
// Strioctl Helpers
1127

1128
func (s *Strioctl) SetInt(i int) {
1129
	s.Len = int32(unsafe.Sizeof(i))
1130
	s.Dp = (*int8)(unsafe.Pointer(&i))
1131
}
1132

1133
func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
1134
	return ioctlPtrRet(fd, req, unsafe.Pointer(s))
1135
}
1136

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.