github.com/etecs-ru/go-sys-wineventlog@v0.0.0-20210227233244-4c3abb794018/unix/syscall_linux_test.go (about) 1 // Copyright 2016 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 //go:build linux 6 // +build linux 7 8 package unix_test 9 10 import ( 11 "bufio" 12 "bytes" 13 "errors" 14 "fmt" 15 "io/ioutil" 16 "os" 17 "path/filepath" 18 "runtime" 19 "runtime/debug" 20 "strconv" 21 "strings" 22 "testing" 23 "time" 24 "unsafe" 25 26 "golang.org/x/sys/unix" 27 ) 28 29 func TestIoctlGetInt(t *testing.T) { 30 f, err := os.Open("/dev/random") 31 if err != nil { 32 t.Fatalf("failed to open device: %v", err) 33 } 34 defer f.Close() 35 36 v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT) 37 if err != nil { 38 t.Fatalf("failed to perform ioctl: %v", err) 39 } 40 41 t.Logf("%d bits of entropy available", v) 42 } 43 44 func TestIoctlRetInt(t *testing.T) { 45 f, err := os.Open("/proc/self/ns/mnt") 46 if err != nil { 47 t.Skipf("skipping test, %v", err) 48 } 49 defer f.Close() 50 51 v, err := unix.IoctlRetInt(int(f.Fd()), unix.NS_GET_NSTYPE) 52 if err != nil { 53 if err == unix.ENOTTY { 54 t.Skipf("old kernel? (need Linux >= 4.11)") 55 } 56 t.Fatalf("failed to perform ioctl: %v", err) 57 } 58 if v != unix.CLONE_NEWNS { 59 t.Fatalf("unexpected return from ioctl; expected %v, got %v", v, unix.CLONE_NEWNS) 60 } 61 } 62 63 func TestIoctlGetRTCTime(t *testing.T) { 64 f, err := os.Open("/dev/rtc0") 65 if err != nil { 66 t.Skipf("skipping test, %v", err) 67 } 68 defer f.Close() 69 70 v, err := unix.IoctlGetRTCTime(int(f.Fd())) 71 if err != nil { 72 t.Fatalf("failed to perform ioctl: %v", err) 73 } 74 75 t.Logf("RTC time: %04d-%02d-%02d %02d:%02d:%02d", v.Year+1900, v.Mon+1, v.Mday, v.Hour, v.Min, v.Sec) 76 } 77 78 func TestIoctlGetRTCWkAlrm(t *testing.T) { 79 f, err := os.Open("/dev/rtc0") 80 if err != nil { 81 t.Skipf("skipping test, %v", err) 82 } 83 defer f.Close() 84 85 v, err := unix.IoctlGetRTCWkAlrm(int(f.Fd())) 86 if err != nil { 87 t.Fatalf("failed to perform ioctl: %v", err) 88 } 89 90 t.Logf("RTC wake alarm enabled '%d'; time: %04d-%02d-%02d %02d:%02d:%02d", 91 v.Enabled, v.Time.Year+1900, v.Time.Mon+1, v.Time.Mday, v.Time.Hour, v.Time.Min, v.Time.Sec) 92 } 93 94 func TestPpoll(t *testing.T) { 95 if runtime.GOOS == "android" { 96 t.Skip("mkfifo syscall is not available on android, skipping test") 97 } 98 99 defer chtmpdir(t)() 100 f, cleanup := mktmpfifo(t) 101 defer cleanup() 102 103 const timeout = 100 * time.Millisecond 104 105 ok := make(chan bool, 1) 106 go func() { 107 select { 108 case <-time.After(10 * timeout): 109 t.Errorf("Ppoll: failed to timeout after %d", 10*timeout) 110 case <-ok: 111 } 112 }() 113 114 fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}} 115 timeoutTs := unix.NsecToTimespec(int64(timeout)) 116 n, err := unix.Ppoll(fds, &timeoutTs, nil) 117 ok <- true 118 if err != nil { 119 t.Errorf("Ppoll: unexpected error: %v", err) 120 return 121 } 122 if n != 0 { 123 t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0) 124 return 125 } 126 } 127 128 func TestTime(t *testing.T) { 129 var ut unix.Time_t 130 ut2, err := unix.Time(&ut) 131 if err != nil { 132 t.Fatalf("Time: %v", err) 133 } 134 if ut != ut2 { 135 t.Errorf("Time: return value %v should be equal to argument %v", ut2, ut) 136 } 137 138 var now time.Time 139 140 for i := 0; i < 10; i++ { 141 ut, err = unix.Time(nil) 142 if err != nil { 143 t.Fatalf("Time: %v", err) 144 } 145 146 now = time.Now() 147 diff := int64(ut) - now.Unix() 148 if -1 <= diff && diff <= 1 { 149 return 150 } 151 } 152 153 t.Errorf("Time: return value %v should be nearly equal to time.Now().Unix() %v±1", ut, now.Unix()) 154 } 155 156 func TestUtime(t *testing.T) { 157 defer chtmpdir(t)() 158 159 touch(t, "file1") 160 161 buf := &unix.Utimbuf{ 162 Modtime: 12345, 163 } 164 165 err := unix.Utime("file1", buf) 166 if err != nil { 167 t.Fatalf("Utime: %v", err) 168 } 169 170 fi, err := os.Stat("file1") 171 if err != nil { 172 t.Fatal(err) 173 } 174 175 if fi.ModTime().Unix() != 12345 { 176 t.Errorf("Utime: failed to change modtime: expected %v, got %v", 12345, fi.ModTime().Unix()) 177 } 178 } 179 180 func TestRlimitAs(t *testing.T) { 181 // disable GC during to avoid flaky test 182 defer debug.SetGCPercent(debug.SetGCPercent(-1)) 183 184 var rlim unix.Rlimit 185 err := unix.Getrlimit(unix.RLIMIT_AS, &rlim) 186 if err != nil { 187 t.Fatalf("Getrlimit: %v", err) 188 } 189 var zero unix.Rlimit 190 if zero == rlim { 191 t.Fatalf("Getrlimit: got zero value %#v", rlim) 192 } 193 set := rlim 194 set.Cur = uint64(unix.Getpagesize()) 195 err = unix.Setrlimit(unix.RLIMIT_AS, &set) 196 if err != nil { 197 t.Fatalf("Setrlimit: set failed: %#v %v", set, err) 198 } 199 200 // RLIMIT_AS was set to the page size, so mmap()'ing twice the page size 201 // should fail. See 'man 2 getrlimit'. 202 _, err = unix.Mmap(-1, 0, 2*unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE) 203 if err == nil { 204 t.Fatal("Mmap: unexpectedly succeeded after setting RLIMIT_AS") 205 } 206 207 err = unix.Setrlimit(unix.RLIMIT_AS, &rlim) 208 if err != nil { 209 t.Fatalf("Setrlimit: restore failed: %#v %v", rlim, err) 210 } 211 212 b, err := unix.Mmap(-1, 0, 2*unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE) 213 if err != nil { 214 t.Fatalf("Mmap: %v", err) 215 } 216 err = unix.Munmap(b) 217 if err != nil { 218 t.Fatalf("Munmap: %v", err) 219 } 220 } 221 222 func TestPselect(t *testing.T) { 223 for { 224 n, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, nil) 225 if err == unix.EINTR { 226 t.Logf("Pselect interrupted") 227 continue 228 } else if err != nil { 229 t.Fatalf("Pselect: %v", err) 230 } 231 if n != 0 { 232 t.Fatalf("Pselect: got %v ready file descriptors, expected 0", n) 233 } 234 break 235 } 236 237 dur := 2500 * time.Microsecond 238 var took time.Duration 239 for { 240 // On some platforms (e.g. Linux), the passed-in timespec is 241 // updated by pselect(2). Make sure to reset to the full 242 // duration in case of an EINTR. 243 ts := unix.NsecToTimespec(int64(dur)) 244 start := time.Now() 245 n, err := unix.Pselect(0, nil, nil, nil, &ts, nil) 246 took = time.Since(start) 247 if err == unix.EINTR { 248 t.Logf("Pselect interrupted after %v", took) 249 continue 250 } else if err != nil { 251 t.Fatalf("Pselect: %v", err) 252 } 253 if n != 0 { 254 t.Fatalf("Pselect: got %v ready file descriptors, expected 0", n) 255 } 256 break 257 } 258 259 // On some builder the actual timeout might also be slightly less than the requested. 260 // Add an acceptable margin to avoid flaky tests. 261 if took < dur*2/3 { 262 t.Errorf("Pselect: got %v timeout, expected at least %v", took, dur) 263 } 264 } 265 266 func TestSchedSetaffinity(t *testing.T) { 267 var newMask unix.CPUSet 268 newMask.Zero() 269 if newMask.Count() != 0 { 270 t.Errorf("CpuZero: didn't zero CPU set: %v", newMask) 271 } 272 cpu := 1 273 newMask.Set(cpu) 274 if newMask.Count() != 1 || !newMask.IsSet(cpu) { 275 t.Errorf("CpuSet: didn't set CPU %d in set: %v", cpu, newMask) 276 } 277 cpu = 5 278 newMask.Set(cpu) 279 if newMask.Count() != 2 || !newMask.IsSet(cpu) { 280 t.Errorf("CpuSet: didn't set CPU %d in set: %v", cpu, newMask) 281 } 282 newMask.Clear(cpu) 283 if newMask.Count() != 1 || newMask.IsSet(cpu) { 284 t.Errorf("CpuClr: didn't clear CPU %d in set: %v", cpu, newMask) 285 } 286 287 runtime.LockOSThread() 288 defer runtime.UnlockOSThread() 289 290 var oldMask unix.CPUSet 291 err := unix.SchedGetaffinity(0, &oldMask) 292 if err != nil { 293 t.Fatalf("SchedGetaffinity: %v", err) 294 } 295 296 if runtime.NumCPU() < 2 { 297 t.Skip("skipping setaffinity tests on single CPU system") 298 } 299 if runtime.GOOS == "android" { 300 t.Skip("skipping setaffinity tests on android") 301 } 302 303 // On a system like ppc64x where some cores can be disabled using ppc64_cpu, 304 // setaffinity should only be called with enabled cores. The valid cores 305 // are found from the oldMask, but if none are found then the setaffinity 306 // tests are skipped. Issue #27875. 307 cpu = 1 308 if !oldMask.IsSet(cpu) { 309 newMask.Zero() 310 for i := 0; i < len(oldMask); i++ { 311 if oldMask.IsSet(i) { 312 newMask.Set(i) 313 break 314 } 315 } 316 if newMask.Count() == 0 { 317 t.Skip("skipping setaffinity tests if CPU not available") 318 } 319 } 320 321 err = unix.SchedSetaffinity(0, &newMask) 322 if err != nil { 323 t.Fatalf("SchedSetaffinity: %v", err) 324 } 325 326 var gotMask unix.CPUSet 327 err = unix.SchedGetaffinity(0, &gotMask) 328 if err != nil { 329 t.Fatalf("SchedGetaffinity: %v", err) 330 } 331 332 if gotMask != newMask { 333 t.Errorf("SchedSetaffinity: returned affinity mask does not match set affinity mask") 334 } 335 336 // Restore old mask so it doesn't affect successive tests 337 err = unix.SchedSetaffinity(0, &oldMask) 338 if err != nil { 339 t.Fatalf("SchedSetaffinity: %v", err) 340 } 341 } 342 343 func TestStatx(t *testing.T) { 344 var stx unix.Statx_t 345 err := unix.Statx(unix.AT_FDCWD, ".", 0, 0, &stx) 346 if err == unix.ENOSYS || err == unix.EPERM { 347 t.Skip("statx syscall is not available, skipping test") 348 } else if err != nil { 349 t.Fatalf("Statx: %v", err) 350 } 351 352 defer chtmpdir(t)() 353 touch(t, "file1") 354 355 var st unix.Stat_t 356 err = unix.Stat("file1", &st) 357 if err != nil { 358 t.Fatalf("Stat: %v", err) 359 } 360 361 flags := unix.AT_STATX_SYNC_AS_STAT 362 err = unix.Statx(unix.AT_FDCWD, "file1", flags, unix.STATX_ALL, &stx) 363 if err != nil { 364 t.Fatalf("Statx: %v", err) 365 } 366 367 if uint32(stx.Mode) != st.Mode { 368 t.Errorf("Statx: returned stat mode does not match Stat") 369 } 370 371 ctime := unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)} 372 mtime := unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)} 373 374 if stx.Ctime != ctime { 375 t.Errorf("Statx: returned stat ctime does not match Stat") 376 } 377 if stx.Mtime != mtime { 378 t.Errorf("Statx: returned stat mtime does not match Stat") 379 } 380 381 err = os.Symlink("file1", "symlink1") 382 if err != nil { 383 t.Fatal(err) 384 } 385 386 err = unix.Lstat("symlink1", &st) 387 if err != nil { 388 t.Fatalf("Lstat: %v", err) 389 } 390 391 err = unix.Statx(unix.AT_FDCWD, "symlink1", flags, unix.STATX_BASIC_STATS, &stx) 392 if err != nil { 393 t.Fatalf("Statx: %v", err) 394 } 395 396 // follow symlink, expect a regulat file 397 if stx.Mode&unix.S_IFREG == 0 { 398 t.Errorf("Statx: didn't follow symlink") 399 } 400 401 err = unix.Statx(unix.AT_FDCWD, "symlink1", flags|unix.AT_SYMLINK_NOFOLLOW, unix.STATX_ALL, &stx) 402 if err != nil { 403 t.Fatalf("Statx: %v", err) 404 } 405 406 // follow symlink, expect a symlink 407 if stx.Mode&unix.S_IFLNK == 0 { 408 t.Errorf("Statx: unexpectedly followed symlink") 409 } 410 if uint32(stx.Mode) != st.Mode { 411 t.Errorf("Statx: returned stat mode does not match Lstat") 412 } 413 414 ctime = unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)} 415 mtime = unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)} 416 417 if stx.Ctime != ctime { 418 t.Errorf("Statx: returned stat ctime does not match Lstat") 419 } 420 if stx.Mtime != mtime { 421 t.Errorf("Statx: returned stat mtime does not match Lstat") 422 } 423 } 424 425 // stringsFromByteSlice converts a sequence of attributes to a []string. 426 // On Linux, each entry is a NULL-terminated string. 427 func stringsFromByteSlice(buf []byte) []string { 428 var result []string 429 off := 0 430 for i, b := range buf { 431 if b == 0 { 432 result = append(result, string(buf[off:i])) 433 off = i + 1 434 } 435 } 436 return result 437 } 438 439 func TestFaccessat(t *testing.T) { 440 defer chtmpdir(t)() 441 touch(t, "file1") 442 443 err := unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, 0) 444 if err != nil { 445 t.Errorf("Faccessat: unexpected error: %v", err) 446 } 447 448 err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, 2) 449 if err != unix.EINVAL { 450 t.Errorf("Faccessat: unexpected error: %v, want EINVAL", err) 451 } 452 453 err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, unix.AT_EACCESS) 454 if err != nil { 455 t.Errorf("Faccessat: unexpected error: %v", err) 456 } 457 458 err = os.Symlink("file1", "symlink1") 459 if err != nil { 460 t.Fatal(err) 461 } 462 463 err = unix.Faccessat(unix.AT_FDCWD, "symlink1", unix.R_OK, unix.AT_SYMLINK_NOFOLLOW) 464 if err != nil { 465 t.Errorf("Faccessat SYMLINK_NOFOLLOW: unexpected error %v", err) 466 } 467 468 // We can't really test AT_SYMLINK_NOFOLLOW, because there 469 // doesn't seem to be any way to change the mode of a symlink. 470 // We don't test AT_EACCESS because such tests are only 471 // meaningful if run as root. 472 473 err = unix.Fchmodat(unix.AT_FDCWD, "file1", 0, 0) 474 if err != nil { 475 t.Errorf("Fchmodat: unexpected error %v", err) 476 } 477 478 err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.F_OK, unix.AT_SYMLINK_NOFOLLOW) 479 if err != nil { 480 t.Errorf("Faccessat: unexpected error: %v", err) 481 } 482 483 err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, unix.AT_SYMLINK_NOFOLLOW) 484 if err != unix.EACCES { 485 if unix.Getuid() != 0 { 486 t.Errorf("Faccessat: unexpected error: %v, want EACCES", err) 487 } 488 } 489 } 490 491 func TestSyncFileRange(t *testing.T) { 492 file, err := ioutil.TempFile("", "TestSyncFileRange") 493 if err != nil { 494 t.Fatal(err) 495 } 496 defer os.Remove(file.Name()) 497 defer file.Close() 498 499 err = unix.SyncFileRange(int(file.Fd()), 0, 0, 0) 500 if err == unix.ENOSYS || err == unix.EPERM { 501 t.Skip("sync_file_range syscall is not available, skipping test") 502 } else if err != nil { 503 t.Fatalf("SyncFileRange: %v", err) 504 } 505 506 // invalid flags 507 flags := 0xf00 508 err = unix.SyncFileRange(int(file.Fd()), 0, 0, flags) 509 if err != unix.EINVAL { 510 t.Fatalf("SyncFileRange: unexpected error: %v, want EINVAL", err) 511 } 512 } 513 514 func TestClockNanosleep(t *testing.T) { 515 delay := 50 * time.Millisecond 516 517 // Relative timespec. 518 start := time.Now() 519 rel := unix.NsecToTimespec(delay.Nanoseconds()) 520 remain := unix.Timespec{} 521 for { 522 err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, &remain) 523 if err == unix.ENOSYS || err == unix.EPERM { 524 t.Skip("clock_nanosleep syscall is not available, skipping test") 525 } else if err == unix.EINTR { 526 t.Logf("ClockNanosleep interrupted after %v", time.Since(start)) 527 rel = remain 528 continue 529 } else if err != nil { 530 t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) = %v", &rel, err) 531 } else if slept := time.Since(start); slept < delay { 532 t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) slept only %v", &rel, slept) 533 } 534 break 535 } 536 537 // Absolute timespec. 538 for { 539 start = time.Now() 540 until := start.Add(delay) 541 abs := unix.NsecToTimespec(until.UnixNano()) 542 err := unix.ClockNanosleep(unix.CLOCK_REALTIME, unix.TIMER_ABSTIME, &abs, nil) 543 if err == unix.EINTR { 544 t.Logf("ClockNanosleep interrupted after %v", time.Since(start)) 545 continue 546 } else if err != nil { 547 t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) = %v", &abs, until, err) 548 } else if slept := time.Since(start); slept < delay { 549 t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) slept only %v", &abs, until, slept) 550 } 551 break 552 } 553 554 // Invalid clock. clock_nanosleep(2) says EINVAL, but it’s actually EOPNOTSUPP. 555 err := unix.ClockNanosleep(unix.CLOCK_THREAD_CPUTIME_ID, 0, &rel, nil) 556 if err != unix.EINVAL && err != unix.EOPNOTSUPP { 557 t.Errorf("ClockNanosleep(CLOCK_THREAD_CPUTIME_ID, 0, %#v, nil) = %v, want EINVAL or EOPNOTSUPP", &rel, err) 558 } 559 } 560 561 func TestOpenByHandleAt(t *testing.T) { 562 skipIfNotSupported := func(t *testing.T, name string, err error) { 563 if err == unix.EPERM { 564 t.Skipf("skipping %s test without CAP_DAC_READ_SEARCH", name) 565 } 566 if err == unix.ENOSYS { 567 t.Skipf("%s system call not available", name) 568 } 569 if err == unix.EOPNOTSUPP { 570 t.Skipf("%s not supported on this filesystem", name) 571 } 572 } 573 574 h, mountID, err := unix.NameToHandleAt(unix.AT_FDCWD, "syscall_linux_test.go", 0) 575 if err != nil { 576 skipIfNotSupported(t, "name_to_handle_at", err) 577 t.Fatalf("NameToHandleAt: %v", err) 578 } 579 t.Logf("mountID: %v, handle: size=%d, type=%d, bytes=%q", mountID, 580 h.Size(), h.Type(), h.Bytes()) 581 mount, err := openMountByID(mountID) 582 if err != nil { 583 t.Fatalf("openMountByID: %v", err) 584 } 585 defer mount.Close() 586 587 for _, clone := range []bool{false, true} { 588 t.Run("clone="+strconv.FormatBool(clone), func(t *testing.T) { 589 if clone { 590 h = unix.NewFileHandle(h.Type(), h.Bytes()) 591 } 592 fd, err := unix.OpenByHandleAt(int(mount.Fd()), h, unix.O_RDONLY) 593 skipIfNotSupported(t, "open_by_handle_at", err) 594 if err != nil { 595 t.Fatalf("OpenByHandleAt: %v", err) 596 } 597 defer unix.Close(fd) 598 599 t.Logf("opened fd %v", fd) 600 f := os.NewFile(uintptr(fd), "") 601 slurp, err := ioutil.ReadAll(f) 602 if err != nil { 603 t.Fatal(err) 604 } 605 const substr = "Some substring for a test." 606 if !strings.Contains(string(slurp), substr) { 607 t.Errorf("didn't find substring %q in opened file; read %d bytes", substr, len(slurp)) 608 } 609 }) 610 } 611 } 612 613 func openMountByID(mountID int) (f *os.File, err error) { 614 mi, err := os.Open("/proc/self/mountinfo") 615 if err != nil { 616 return nil, err 617 } 618 defer mi.Close() 619 bs := bufio.NewScanner(mi) 620 wantPrefix := []byte(fmt.Sprintf("%v ", mountID)) 621 for bs.Scan() { 622 if !bytes.HasPrefix(bs.Bytes(), wantPrefix) { 623 continue 624 } 625 fields := strings.Fields(bs.Text()) 626 dev := fields[4] 627 return os.Open(dev) 628 } 629 if err := bs.Err(); err != nil { 630 return nil, err 631 } 632 return nil, errors.New("mountID not found") 633 } 634 635 func TestEpoll(t *testing.T) { 636 efd, err := unix.EpollCreate1(unix.EPOLL_CLOEXEC) 637 if err != nil { 638 t.Fatalf("EpollCreate1: %v", err) 639 } 640 defer unix.Close(efd) 641 642 r, w, err := os.Pipe() 643 if err != nil { 644 t.Fatal(err) 645 } 646 defer r.Close() 647 defer w.Close() 648 649 fd := int(r.Fd()) 650 ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)} 651 652 err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev) 653 if err != nil { 654 t.Fatalf("EpollCtl: %v", err) 655 } 656 657 if _, err := w.Write([]byte("HELLO GOPHER")); err != nil { 658 t.Fatal(err) 659 } 660 661 events := make([]unix.EpollEvent, 128) 662 n, err := unix.EpollWait(efd, events, 1) 663 if err != nil { 664 t.Fatalf("EpollWait: %v", err) 665 } 666 667 if n != 1 { 668 t.Errorf("EpollWait: wrong number of events: got %v, expected 1", n) 669 } 670 671 got := int(events[0].Fd) 672 if got != fd { 673 t.Errorf("EpollWait: wrong Fd in event: got %v, expected %v", got, fd) 674 } 675 } 676 677 func TestPrctlRetInt(t *testing.T) { 678 err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) 679 if err != nil { 680 t.Skipf("Prctl: %v, skipping test", err) 681 } 682 v, err := unix.PrctlRetInt(unix.PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) 683 if err != nil { 684 t.Fatalf("failed to perform prctl: %v", err) 685 } 686 if v != 1 { 687 t.Fatalf("unexpected return from prctl; got %v, expected %v", v, 1) 688 } 689 } 690 691 func TestTimerfd(t *testing.T) { 692 var now unix.Timespec 693 if err := unix.ClockGettime(unix.CLOCK_REALTIME, &now); err != nil { 694 t.Fatalf("ClockGettime: %v", err) 695 } 696 697 tfd, err := unix.TimerfdCreate(unix.CLOCK_REALTIME, 0) 698 if err == unix.ENOSYS { 699 t.Skip("timerfd_create system call not implemented") 700 } else if err != nil { 701 t.Fatalf("TimerfdCreate: %v", err) 702 } 703 defer unix.Close(tfd) 704 705 var timeSpec unix.ItimerSpec 706 if err := unix.TimerfdGettime(tfd, &timeSpec); err != nil { 707 t.Fatalf("TimerfdGettime: %v", err) 708 } 709 710 if timeSpec.Value.Nsec != 0 || timeSpec.Value.Sec != 0 { 711 t.Fatalf("TimerfdGettime: timer is already set, but shouldn't be") 712 } 713 714 timeSpec = unix.ItimerSpec{ 715 Interval: unix.NsecToTimespec(int64(time.Millisecond)), 716 Value: now, 717 } 718 719 if err := unix.TimerfdSettime(tfd, unix.TFD_TIMER_ABSTIME, &timeSpec, nil); err != nil { 720 t.Fatalf("TimerfdSettime: %v", err) 721 } 722 723 const totalTicks = 10 724 const bufferLength = 8 725 726 buffer := make([]byte, bufferLength) 727 728 var count uint64 = 0 729 for count < totalTicks { 730 n, err := unix.Read(tfd, buffer) 731 if err != nil { 732 t.Fatalf("Timerfd: %v", err) 733 } else if n != bufferLength { 734 t.Fatalf("Timerfd: got %d bytes from timerfd, expected %d bytes", n, bufferLength) 735 } 736 737 count += *(*uint64)(unsafe.Pointer(&buffer)) 738 } 739 } 740 741 func TestOpenat2(t *testing.T) { 742 how := &unix.OpenHow{ 743 Flags: unix.O_RDONLY, 744 } 745 fd, err := unix.Openat2(unix.AT_FDCWD, ".", how) 746 if err != nil { 747 if err == unix.ENOSYS || err == unix.EPERM { 748 t.Skipf("openat2: %v (old kernel? need Linux >= 5.6)", err) 749 } 750 t.Fatalf("openat2: %v", err) 751 } 752 if err := unix.Close(fd); err != nil { 753 t.Fatalf("close: %v", err) 754 } 755 756 // prepare 757 tempDir, err := ioutil.TempDir("", t.Name()) 758 if err != nil { 759 t.Fatal(err) 760 } 761 defer os.RemoveAll(tempDir) 762 763 subdir := filepath.Join(tempDir, "dir") 764 if err := os.Mkdir(subdir, 0755); err != nil { 765 t.Fatal(err) 766 } 767 symlink := filepath.Join(subdir, "symlink") 768 if err := os.Symlink("../", symlink); err != nil { 769 t.Fatal(err) 770 } 771 772 dirfd, err := unix.Open(subdir, unix.O_RDONLY, 0) 773 if err != nil { 774 t.Fatalf("open(%q): %v", subdir, err) 775 } 776 defer unix.Close(dirfd) 777 778 // openat2 with no extra flags -- should succeed 779 fd, err = unix.Openat2(dirfd, "symlink", how) 780 if err != nil { 781 t.Errorf("Openat2 should succeed, got %v", err) 782 } 783 if err := unix.Close(fd); err != nil { 784 t.Fatalf("close: %v", err) 785 } 786 787 // open with RESOLVE_BENEATH, should result in EXDEV 788 how.Resolve = unix.RESOLVE_BENEATH 789 fd, err = unix.Openat2(dirfd, "symlink", how) 790 if err == nil { 791 if err := unix.Close(fd); err != nil { 792 t.Fatalf("close: %v", err) 793 } 794 } 795 if err != unix.EXDEV { 796 t.Errorf("Openat2 should fail with EXDEV, got %v", err) 797 } 798 } 799 800 func TestIoctlFileDedupeRange(t *testing.T) { 801 f1, err := ioutil.TempFile("", t.Name()) 802 if err != nil { 803 t.Fatal(err) 804 } 805 defer f1.Close() 806 defer os.Remove(f1.Name()) 807 808 // Test deduplication with two blocks of zeros 809 data := make([]byte, 4096) 810 811 for i := 0; i < 2; i += 1 { 812 _, err = f1.Write(data) 813 if err != nil { 814 t.Fatal(err) 815 } 816 } 817 818 f2, err := ioutil.TempFile("", t.Name()) 819 if err != nil { 820 t.Fatal(err) 821 } 822 defer f2.Close() 823 defer os.Remove(f2.Name()) 824 825 for i := 0; i < 2; i += 1 { 826 // Make the 2nd block different 827 if i == 1 { 828 data[1] = 1 829 } 830 831 _, err = f2.Write(data) 832 if err != nil { 833 t.Fatal(err) 834 } 835 } 836 837 dedupe := unix.FileDedupeRange{ 838 Src_offset: uint64(0), 839 Src_length: uint64(4096), 840 Info: []unix.FileDedupeRangeInfo{ 841 unix.FileDedupeRangeInfo{ 842 Dest_fd: int64(f2.Fd()), 843 Dest_offset: uint64(0), 844 }, 845 unix.FileDedupeRangeInfo{ 846 Dest_fd: int64(f2.Fd()), 847 Dest_offset: uint64(4096), 848 }, 849 }} 850 851 err = unix.IoctlFileDedupeRange(int(f1.Fd()), &dedupe) 852 if err == unix.EOPNOTSUPP || err == unix.EINVAL || err == unix.ENOTTY { 853 t.Skip("deduplication not supported on this filesystem") 854 } else if err != nil { 855 t.Fatal(err) 856 } 857 858 // The first Info should be equal 859 if dedupe.Info[0].Status < 0 { 860 errno := unix.Errno(-dedupe.Info[0].Status) 861 if errno == unix.EINVAL { 862 t.Skip("deduplication not supported on this filesystem") 863 } 864 t.Errorf("Unexpected error in FileDedupeRange: %s", unix.ErrnoName(errno)) 865 } else if dedupe.Info[0].Status == unix.FILE_DEDUPE_RANGE_DIFFERS { 866 t.Errorf("Unexpected different bytes in FileDedupeRange") 867 } 868 if dedupe.Info[0].Bytes_deduped != 4096 { 869 t.Errorf("Unexpected amount of bytes deduped %v != %v", 870 dedupe.Info[0].Bytes_deduped, 4096) 871 } 872 873 // The second Info should be different 874 if dedupe.Info[1].Status < 0 { 875 errno := unix.Errno(-dedupe.Info[1].Status) 876 if errno == unix.EINVAL { 877 t.Skip("deduplication not supported on this filesystem") 878 } 879 t.Errorf("Unexpected error in FileDedupeRange: %s", unix.ErrnoName(errno)) 880 } else if dedupe.Info[1].Status == unix.FILE_DEDUPE_RANGE_SAME { 881 t.Errorf("Unexpected equal bytes in FileDedupeRange") 882 } 883 if dedupe.Info[1].Bytes_deduped != 0 { 884 t.Errorf("Unexpected amount of bytes deduped %v != %v", 885 dedupe.Info[1].Bytes_deduped, 0) 886 } 887 }