Source file src/syscall/syscall_freebsd.go
1
2
3
4
5
6
7
8
9
10
11
12
13 package syscall
14
15 import (
16 "sync"
17 "unsafe"
18 )
19
20 const (
21 _SYS_FSTAT_FREEBSD12 = 551
22 _SYS_FSTATAT_FREEBSD12 = 552
23 _SYS_GETDIRENTRIES_FREEBSD12 = 554
24 _SYS_STATFS_FREEBSD12 = 555
25 _SYS_FSTATFS_FREEBSD12 = 556
26 _SYS_GETFSSTAT_FREEBSD12 = 557
27 _SYS_MKNODAT_FREEBSD12 = 559
28 )
29
30
31 var (
32 osreldateOnce sync.Once
33 osreldate uint32
34 )
35
36
37 const _ino64First = 1200031
38
39 func supportsABI(ver uint32) bool {
40 osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") })
41 return osreldate >= ver
42 }
43
44 type SockaddrDatalink struct {
45 Len uint8
46 Family uint8
47 Index uint16
48 Type uint8
49 Nlen uint8
50 Alen uint8
51 Slen uint8
52 Data [46]int8
53 raw RawSockaddrDatalink
54 }
55
56
57 func nametomib(name string) (mib []_C_int, err error) {
58 const siz = unsafe.Sizeof(mib[0])
59
60
61
62
63
64
65
66
67 var buf [CTL_MAXNAME + 2]_C_int
68 n := uintptr(CTL_MAXNAME) * siz
69
70 p := (*byte)(unsafe.Pointer(&buf[0]))
71 bytes, err := ByteSliceFromString(name)
72 if err != nil {
73 return nil, err
74 }
75
76
77
78 if err = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); err != nil {
79 return nil, err
80 }
81 return buf[0 : n/siz], nil
82 }
83
84 func direntIno(buf []byte) (uint64, bool) {
85 return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
86 }
87
88 func direntReclen(buf []byte) (uint64, bool) {
89 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
90 }
91
92 func direntNamlen(buf []byte) (uint64, bool) {
93 return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
94 }
95
96 func Pipe(p []int) error {
97 return Pipe2(p, 0)
98 }
99
100
101
102 func Pipe2(p []int, flags int) error {
103 if len(p) != 2 {
104 return EINVAL
105 }
106 var pp [2]_C_int
107 err := pipe2(&pp, flags)
108 p[0] = int(pp[0])
109 p[1] = int(pp[1])
110 return err
111 }
112
113 func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
114 var value IPMreqn
115 vallen := _Socklen(SizeofIPMreqn)
116 errno := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
117 return &value, errno
118 }
119
120 func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
121 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
122 }
123
124 func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
125 var rsa RawSockaddrAny
126 var len _Socklen = SizeofSockaddrAny
127 nfd, err = accept4(fd, &rsa, &len, flags)
128 if err != nil {
129 return
130 }
131 if len > SizeofSockaddrAny {
132 panic("RawSockaddrAny too small")
133 }
134 sa, err = anyToSockaddr(&rsa)
135 if err != nil {
136 Close(nfd)
137 nfd = 0
138 }
139 return
140 }
141
142 func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
143 var (
144 _p0 unsafe.Pointer
145 bufsize uintptr
146 oldBuf []statfs_freebsd11_t
147 needsConvert bool
148 )
149
150 if len(buf) > 0 {
151 if supportsABI(_ino64First) {
152 _p0 = unsafe.Pointer(&buf[0])
153 bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
154 } else {
155 n := len(buf)
156 oldBuf = make([]statfs_freebsd11_t, n)
157 _p0 = unsafe.Pointer(&oldBuf[0])
158 bufsize = unsafe.Sizeof(statfs_freebsd11_t{}) * uintptr(n)
159 needsConvert = true
160 }
161 }
162 var sysno uintptr = SYS_GETFSSTAT
163 if supportsABI(_ino64First) {
164 sysno = _SYS_GETFSSTAT_FREEBSD12
165 }
166 r0, _, e1 := Syscall(sysno, uintptr(_p0), bufsize, uintptr(flags))
167 n = int(r0)
168 if e1 != 0 {
169 err = e1
170 }
171 if e1 == 0 && needsConvert {
172 for i := range oldBuf {
173 buf[i].convertFrom(&oldBuf[i])
174 }
175 }
176 return
177 }
178
179 func setattrlistTimes(path string, times []Timespec) error {
180
181 return ENOSYS
182 }
183
184 func Stat(path string, st *Stat_t) (err error) {
185 var oldStat stat_freebsd11_t
186 if supportsABI(_ino64First) {
187 return fstatat_freebsd12(_AT_FDCWD, path, st, 0)
188 }
189 err = stat(path, &oldStat)
190 if err != nil {
191 return err
192 }
193
194 st.convertFrom(&oldStat)
195 return nil
196 }
197
198 func Lstat(path string, st *Stat_t) (err error) {
199 var oldStat stat_freebsd11_t
200 if supportsABI(_ino64First) {
201 return fstatat_freebsd12(_AT_FDCWD, path, st, _AT_SYMLINK_NOFOLLOW)
202 }
203 err = lstat(path, &oldStat)
204 if err != nil {
205 return err
206 }
207
208 st.convertFrom(&oldStat)
209 return nil
210 }
211
212 func Fstat(fd int, st *Stat_t) (err error) {
213 var oldStat stat_freebsd11_t
214 if supportsABI(_ino64First) {
215 return fstat_freebsd12(fd, st)
216 }
217 err = fstat(fd, &oldStat)
218 if err != nil {
219 return err
220 }
221
222 st.convertFrom(&oldStat)
223 return nil
224 }
225
226 func Fstatat(fd int, path string, st *Stat_t, flags int) (err error) {
227 var oldStat stat_freebsd11_t
228 if supportsABI(_ino64First) {
229 return fstatat_freebsd12(fd, path, st, flags)
230 }
231 err = fstatat(fd, path, &oldStat, flags)
232 if err != nil {
233 return err
234 }
235
236 st.convertFrom(&oldStat)
237 return nil
238 }
239
240 func Statfs(path string, st *Statfs_t) (err error) {
241 var oldStatfs statfs_freebsd11_t
242 if supportsABI(_ino64First) {
243 return statfs_freebsd12(path, st)
244 }
245 err = statfs(path, &oldStatfs)
246 if err != nil {
247 return err
248 }
249
250 st.convertFrom(&oldStatfs)
251 return nil
252 }
253
254 func Fstatfs(fd int, st *Statfs_t) (err error) {
255 var oldStatfs statfs_freebsd11_t
256 if supportsABI(_ino64First) {
257 return fstatfs_freebsd12(fd, st)
258 }
259 err = fstatfs(fd, &oldStatfs)
260 if err != nil {
261 return err
262 }
263
264 st.convertFrom(&oldStatfs)
265 return nil
266 }
267
268 func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
269 if supportsABI(_ino64First) {
270 if basep == nil || unsafe.Sizeof(*basep) == 8 {
271 return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep)))
272 }
273
274
275 var base uint64 = uint64(*basep)
276 n, err = getdirentries_freebsd12(fd, buf, &base)
277 *basep = uintptr(base)
278 if base>>32 != 0 {
279
280
281
282 err = EIO
283 }
284 return
285 }
286
287
288
289 oldBufLen := roundup(len(buf)/4, _dirblksiz)
290 oldBuf := make([]byte, oldBufLen)
291 n, err = getdirentries(fd, oldBuf, basep)
292 if err == nil && n > 0 {
293 n = convertFromDirents11(buf, oldBuf[:n])
294 }
295 return
296 }
297
298 func Mknod(path string, mode uint32, dev uint64) (err error) {
299 var oldDev int
300 if supportsABI(_ino64First) {
301 return mknodat_freebsd12(_AT_FDCWD, path, mode, dev)
302 }
303 oldDev = int(dev)
304 return mknod(path, mode, oldDev)
305 }
306
307
308
309
310
311 func roundup(x, y int) int {
312 return ((x + y - 1) / y) * y
313 }
314
315 func (s *Stat_t) convertFrom(old *stat_freebsd11_t) {
316 *s = Stat_t{
317 Dev: uint64(old.Dev),
318 Ino: uint64(old.Ino),
319 Nlink: uint64(old.Nlink),
320 Mode: old.Mode,
321 Uid: old.Uid,
322 Gid: old.Gid,
323 Rdev: uint64(old.Rdev),
324 Atimespec: old.Atimespec,
325 Mtimespec: old.Mtimespec,
326 Ctimespec: old.Ctimespec,
327 Birthtimespec: old.Birthtimespec,
328 Size: old.Size,
329 Blocks: old.Blocks,
330 Blksize: old.Blksize,
331 Flags: old.Flags,
332 Gen: uint64(old.Gen),
333 }
334 }
335
336 func (s *Statfs_t) convertFrom(old *statfs_freebsd11_t) {
337 *s = Statfs_t{
338 Version: _statfsVersion,
339 Type: old.Type,
340 Flags: old.Flags,
341 Bsize: old.Bsize,
342 Iosize: old.Iosize,
343 Blocks: old.Blocks,
344 Bfree: old.Bfree,
345 Bavail: old.Bavail,
346 Files: old.Files,
347 Ffree: old.Ffree,
348 Syncwrites: old.Syncwrites,
349 Asyncwrites: old.Asyncwrites,
350 Syncreads: old.Syncreads,
351 Asyncreads: old.Asyncreads,
352
353 Namemax: old.Namemax,
354 Owner: old.Owner,
355 Fsid: old.Fsid,
356
357
358
359
360 }
361
362 sl := old.Fstypename[:]
363 n := clen(*(*[]byte)(unsafe.Pointer(&sl)))
364 copy(s.Fstypename[:], old.Fstypename[:n])
365
366 sl = old.Mntfromname[:]
367 n = clen(*(*[]byte)(unsafe.Pointer(&sl)))
368 copy(s.Mntfromname[:], old.Mntfromname[:n])
369
370 sl = old.Mntonname[:]
371 n = clen(*(*[]byte)(unsafe.Pointer(&sl)))
372 copy(s.Mntonname[:], old.Mntonname[:n])
373 }
374
375 func convertFromDirents11(buf []byte, old []byte) int {
376 const (
377 fixedSize = int(unsafe.Offsetof(Dirent{}.Name))
378 oldFixedSize = int(unsafe.Offsetof(dirent_freebsd11{}.Name))
379 )
380
381 dstPos := 0
382 srcPos := 0
383 for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) {
384 dstDirent := (*Dirent)(unsafe.Pointer(&buf[dstPos]))
385 srcDirent := (*dirent_freebsd11)(unsafe.Pointer(&old[srcPos]))
386
387 reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8)
388 if dstPos+reclen > len(buf) {
389 break
390 }
391
392 dstDirent.Fileno = uint64(srcDirent.Fileno)
393 dstDirent.Off = 0
394 dstDirent.Reclen = uint16(reclen)
395 dstDirent.Type = srcDirent.Type
396 dstDirent.Pad0 = 0
397 dstDirent.Namlen = uint16(srcDirent.Namlen)
398 dstDirent.Pad1 = 0
399
400 copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen])
401 padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen]
402 for i := range padding {
403 padding[i] = 0
404 }
405
406 dstPos += int(dstDirent.Reclen)
407 srcPos += int(srcDirent.Reclen)
408 }
409
410 return dstPos
411 }
412
413
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
View as plain text