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 if err == nil {
109 p[0] = int(pp[0])
110 p[1] = int(pp[1])
111 }
112 return err
113 }
114
115 func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
116 var value IPMreqn
117 vallen := _Socklen(SizeofIPMreqn)
118 errno := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
119 return &value, errno
120 }
121
122 func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
123 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
124 }
125
126 func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
127 var rsa RawSockaddrAny
128 var len _Socklen = SizeofSockaddrAny
129 nfd, err = accept4(fd, &rsa, &len, flags)
130 if err != nil {
131 return
132 }
133 if len > SizeofSockaddrAny {
134 panic("RawSockaddrAny too small")
135 }
136 sa, err = anyToSockaddr(&rsa)
137 if err != nil {
138 Close(nfd)
139 nfd = 0
140 }
141 return
142 }
143
144 func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
145 var (
146 _p0 unsafe.Pointer
147 bufsize uintptr
148 oldBuf []statfs_freebsd11_t
149 needsConvert bool
150 )
151
152 if len(buf) > 0 {
153 if supportsABI(_ino64First) {
154 _p0 = unsafe.Pointer(&buf[0])
155 bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
156 } else {
157 n := len(buf)
158 oldBuf = make([]statfs_freebsd11_t, n)
159 _p0 = unsafe.Pointer(&oldBuf[0])
160 bufsize = unsafe.Sizeof(statfs_freebsd11_t{}) * uintptr(n)
161 needsConvert = true
162 }
163 }
164 var sysno uintptr = SYS_GETFSSTAT
165 if supportsABI(_ino64First) {
166 sysno = _SYS_GETFSSTAT_FREEBSD12
167 }
168 r0, _, e1 := Syscall(sysno, uintptr(_p0), bufsize, uintptr(flags))
169 n = int(r0)
170 if e1 != 0 {
171 err = e1
172 }
173 if e1 == 0 && needsConvert {
174 for i := range oldBuf {
175 buf[i].convertFrom(&oldBuf[i])
176 }
177 }
178 return
179 }
180
181 func Stat(path string, st *Stat_t) (err error) {
182 var oldStat stat_freebsd11_t
183 if supportsABI(_ino64First) {
184 return fstatat_freebsd12(_AT_FDCWD, path, st, 0)
185 }
186 err = stat(path, &oldStat)
187 if err != nil {
188 return err
189 }
190
191 st.convertFrom(&oldStat)
192 return nil
193 }
194
195 func Lstat(path string, st *Stat_t) (err error) {
196 var oldStat stat_freebsd11_t
197 if supportsABI(_ino64First) {
198 return fstatat_freebsd12(_AT_FDCWD, path, st, _AT_SYMLINK_NOFOLLOW)
199 }
200 err = lstat(path, &oldStat)
201 if err != nil {
202 return err
203 }
204
205 st.convertFrom(&oldStat)
206 return nil
207 }
208
209 func Fstat(fd int, st *Stat_t) (err error) {
210 var oldStat stat_freebsd11_t
211 if supportsABI(_ino64First) {
212 return fstat_freebsd12(fd, st)
213 }
214 err = fstat(fd, &oldStat)
215 if err != nil {
216 return err
217 }
218
219 st.convertFrom(&oldStat)
220 return nil
221 }
222
223 func Fstatat(fd int, path string, st *Stat_t, flags int) (err error) {
224 var oldStat stat_freebsd11_t
225 if supportsABI(_ino64First) {
226 return fstatat_freebsd12(fd, path, st, flags)
227 }
228 err = fstatat(fd, path, &oldStat, flags)
229 if err != nil {
230 return err
231 }
232
233 st.convertFrom(&oldStat)
234 return nil
235 }
236
237 func Statfs(path string, st *Statfs_t) (err error) {
238 var oldStatfs statfs_freebsd11_t
239 if supportsABI(_ino64First) {
240 return statfs_freebsd12(path, st)
241 }
242 err = statfs(path, &oldStatfs)
243 if err != nil {
244 return err
245 }
246
247 st.convertFrom(&oldStatfs)
248 return nil
249 }
250
251 func Fstatfs(fd int, st *Statfs_t) (err error) {
252 var oldStatfs statfs_freebsd11_t
253 if supportsABI(_ino64First) {
254 return fstatfs_freebsd12(fd, st)
255 }
256 err = fstatfs(fd, &oldStatfs)
257 if err != nil {
258 return err
259 }
260
261 st.convertFrom(&oldStatfs)
262 return nil
263 }
264
265 func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
266 if supportsABI(_ino64First) {
267 if basep == nil || unsafe.Sizeof(*basep) == 8 {
268 return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep)))
269 }
270
271
272 var base uint64 = uint64(*basep)
273 n, err = getdirentries_freebsd12(fd, buf, &base)
274 *basep = uintptr(base)
275 if base>>32 != 0 {
276
277
278
279 err = EIO
280 }
281 return
282 }
283
284
285
286 oldBufLen := roundup(len(buf)/4, _dirblksiz)
287 oldBuf := make([]byte, oldBufLen)
288 n, err = getdirentries(fd, oldBuf, basep)
289 if err == nil && n > 0 {
290 n = convertFromDirents11(buf, oldBuf[:n])
291 }
292 return
293 }
294
295 func Mknod(path string, mode uint32, dev uint64) (err error) {
296 var oldDev int
297 if supportsABI(_ino64First) {
298 return mknodat_freebsd12(_AT_FDCWD, path, mode, dev)
299 }
300 oldDev = int(dev)
301 return mknod(path, mode, oldDev)
302 }
303
304
305
306
307
308 func roundup(x, y int) int {
309 return ((x + y - 1) / y) * y
310 }
311
312 func (s *Stat_t) convertFrom(old *stat_freebsd11_t) {
313 *s = Stat_t{
314 Dev: uint64(old.Dev),
315 Ino: uint64(old.Ino),
316 Nlink: uint64(old.Nlink),
317 Mode: old.Mode,
318 Uid: old.Uid,
319 Gid: old.Gid,
320 Rdev: uint64(old.Rdev),
321 Atimespec: old.Atimespec,
322 Mtimespec: old.Mtimespec,
323 Ctimespec: old.Ctimespec,
324 Birthtimespec: old.Birthtimespec,
325 Size: old.Size,
326 Blocks: old.Blocks,
327 Blksize: old.Blksize,
328 Flags: old.Flags,
329 Gen: uint64(old.Gen),
330 }
331 }
332
333 func (s *Statfs_t) convertFrom(old *statfs_freebsd11_t) {
334 *s = Statfs_t{
335 Version: _statfsVersion,
336 Type: old.Type,
337 Flags: old.Flags,
338 Bsize: old.Bsize,
339 Iosize: old.Iosize,
340 Blocks: old.Blocks,
341 Bfree: old.Bfree,
342 Bavail: old.Bavail,
343 Files: old.Files,
344 Ffree: old.Ffree,
345 Syncwrites: old.Syncwrites,
346 Asyncwrites: old.Asyncwrites,
347 Syncreads: old.Syncreads,
348 Asyncreads: old.Asyncreads,
349
350 Namemax: old.Namemax,
351 Owner: old.Owner,
352 Fsid: old.Fsid,
353
354
355
356
357 }
358
359 sl := old.Fstypename[:]
360 n := clen(*(*[]byte)(unsafe.Pointer(&sl)))
361 copy(s.Fstypename[:], old.Fstypename[:n])
362
363 sl = old.Mntfromname[:]
364 n = clen(*(*[]byte)(unsafe.Pointer(&sl)))
365 copy(s.Mntfromname[:], old.Mntfromname[:n])
366
367 sl = old.Mntonname[:]
368 n = clen(*(*[]byte)(unsafe.Pointer(&sl)))
369 copy(s.Mntonname[:], old.Mntonname[:n])
370 }
371
372 func convertFromDirents11(buf []byte, old []byte) int {
373 const (
374 fixedSize = int(unsafe.Offsetof(Dirent{}.Name))
375 oldFixedSize = int(unsafe.Offsetof(dirent_freebsd11{}.Name))
376 )
377
378 dstPos := 0
379 srcPos := 0
380 for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) {
381 var dstDirent Dirent
382 var srcDirent dirent_freebsd11
383
384
385
386 copy((*[unsafe.Sizeof(srcDirent)]byte)(unsafe.Pointer(&srcDirent))[:], old[srcPos:])
387
388 reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8)
389 if dstPos+reclen > len(buf) {
390 break
391 }
392
393 dstDirent.Fileno = uint64(srcDirent.Fileno)
394 dstDirent.Off = 0
395 dstDirent.Reclen = uint16(reclen)
396 dstDirent.Type = srcDirent.Type
397 dstDirent.Pad0 = 0
398 dstDirent.Namlen = uint16(srcDirent.Namlen)
399 dstDirent.Pad1 = 0
400
401 copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen])
402 copy(buf[dstPos:], (*[unsafe.Sizeof(dstDirent)]byte)(unsafe.Pointer(&dstDirent))[:])
403 padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen]
404 for i := range padding {
405 padding[i] = 0
406 }
407
408 dstPos += int(dstDirent.Reclen)
409 srcPos += int(srcDirent.Reclen)
410 }
411
412 return dstPos
413 }
414
415
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
511
512
View as plain text