github.com/iceber/iouring-go@v0.0.0-20230403020409-002cfd2e2a90/prep_request.go (about) 1 //go:build linux 2 // +build linux 3 4 package iouring 5 6 import ( 7 "errors" 8 "os" 9 "syscall" 10 "unsafe" 11 12 "golang.org/x/sys/unix" 13 14 iouring_syscall "github.com/iceber/iouring-go/syscall" 15 ) 16 17 type PrepRequest func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) 18 19 // WithInfo request with extra info 20 func (prepReq PrepRequest) WithInfo(info interface{}) PrepRequest { 21 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 22 prepReq(sqe, userData) 23 userData.SetRequestInfo(info) 24 } 25 } 26 27 func (prepReq PrepRequest) WithDrain() PrepRequest { 28 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 29 prepReq(sqe, userData) 30 sqe.SetFlags(iouring_syscall.IOSQE_FLAGS_IO_DRAIN) 31 } 32 } 33 34 func (prepReq PrepRequest) WithCallback(callback RequestCallback) PrepRequest { 35 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 36 prepReq(sqe, userData) 37 userData.SetRequestCallback(callback) 38 } 39 } 40 41 func (iour *IOURing) Read(file *os.File, b []byte, ch chan<- Result) (Request, error) { 42 fd := int(file.Fd()) 43 if fd < 0 { 44 return nil, errors.New("invalid file") 45 } 46 47 return iour.SubmitRequest(Read(fd, b), ch) 48 } 49 50 func (iour *IOURing) Write(file *os.File, b []byte, ch chan<- Result) (Request, error) { 51 fd := int(file.Fd()) 52 if fd < 0 { 53 return nil, errors.New("invalid file") 54 } 55 56 return iour.SubmitRequest(Write(fd, b), ch) 57 } 58 59 func (iour *IOURing) Pread(file *os.File, b []byte, offset uint64, ch chan<- Result) (Request, error) { 60 fd := int(file.Fd()) 61 if fd < 0 { 62 return nil, errors.New("invalid file") 63 } 64 65 return iour.SubmitRequest(Pread(fd, b, offset), ch) 66 } 67 68 func (iour *IOURing) Pwrite(file *os.File, b []byte, offset uint64, ch chan<- Result) (Request, error) { 69 fd := int(file.Fd()) 70 if fd < 0 { 71 return nil, errors.New("invalid file") 72 } 73 74 return iour.SubmitRequest(Pwrite(fd, b, offset), ch) 75 } 76 77 func Nop() PrepRequest { 78 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 79 sqe.PrepOperation(iouring_syscall.IORING_OP_NOP, -1, 0, 0, 0) 80 } 81 } 82 83 func Read(fd int, b []byte) PrepRequest { 84 var bp unsafe.Pointer 85 if len(b) > 0 { 86 bp = unsafe.Pointer(&b[0]) 87 } else { 88 bp = unsafe.Pointer(&_zero) 89 } 90 91 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 92 userData.request.resolver = fdResolver 93 userData.SetRequestBuffer(b, nil) 94 95 sqe.PrepOperation( 96 iouring_syscall.IORING_OP_READ, 97 int32(fd), 98 uint64(uintptr(bp)), 99 uint32(len(b)), 100 0, 101 ) 102 } 103 } 104 105 func Pread(fd int, b []byte, offset uint64) PrepRequest { 106 var bp unsafe.Pointer 107 if len(b) > 0 { 108 bp = unsafe.Pointer(&b[0]) 109 } else { 110 bp = unsafe.Pointer(&_zero) 111 } 112 113 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 114 userData.request.resolver = fdResolver 115 userData.SetRequestBuffer(b, nil) 116 117 sqe.PrepOperation( 118 iouring_syscall.IORING_OP_READ, 119 int32(fd), 120 uint64(uintptr(bp)), 121 uint32(len(b)), 122 uint64(offset), 123 ) 124 } 125 } 126 127 func Write(fd int, b []byte) PrepRequest { 128 var bp unsafe.Pointer 129 if len(b) > 0 { 130 bp = unsafe.Pointer(&b[0]) 131 } else { 132 bp = unsafe.Pointer(&_zero) 133 } 134 135 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 136 userData.request.resolver = fdResolver 137 userData.SetRequestBuffer(b, nil) 138 139 sqe.PrepOperation( 140 iouring_syscall.IORING_OP_WRITE, 141 int32(fd), 142 uint64(uintptr(bp)), 143 uint32(len(b)), 144 0, 145 ) 146 } 147 } 148 149 func Pwrite(fd int, b []byte, offset uint64) PrepRequest { 150 var bp unsafe.Pointer 151 if len(b) > 0 { 152 bp = unsafe.Pointer(&b[0]) 153 } else { 154 bp = unsafe.Pointer(&_zero) 155 } 156 157 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 158 userData.request.resolver = fdResolver 159 userData.SetRequestBuffer(b, nil) 160 161 sqe.PrepOperation( 162 iouring_syscall.IORING_OP_WRITE, 163 int32(fd), 164 uint64(uintptr(bp)), 165 uint32(len(b)), 166 uint64(offset), 167 ) 168 } 169 } 170 171 func Readv(fd int, bs [][]byte) PrepRequest { 172 iovecs := bytes2iovec(bs) 173 174 var bp unsafe.Pointer 175 if len(iovecs) > 0 { 176 bp = unsafe.Pointer(&iovecs[0]) 177 } else { 178 bp = unsafe.Pointer(&_zero) 179 } 180 181 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 182 userData.request.resolver = fdResolver 183 userData.SetRequestBuffers(bs) 184 185 sqe.PrepOperation( 186 iouring_syscall.IORING_OP_READV, 187 int32(fd), 188 uint64(uintptr(bp)), 189 uint32(len(iovecs)), 190 0, 191 ) 192 } 193 } 194 195 func Preadv(fd int, bs [][]byte, offset uint64) PrepRequest { 196 iovecs := bytes2iovec(bs) 197 198 var bp unsafe.Pointer 199 if len(iovecs) > 0 { 200 bp = unsafe.Pointer(&iovecs[0]) 201 } else { 202 bp = unsafe.Pointer(&_zero) 203 } 204 205 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 206 userData.request.resolver = fdResolver 207 userData.SetRequestBuffers(bs) 208 209 sqe.PrepOperation(iouring_syscall.IORING_OP_READV, 210 int32(fd), 211 uint64(uintptr(bp)), 212 uint32(len(iovecs)), 213 offset, 214 ) 215 } 216 } 217 218 func Writev(fd int, bs [][]byte) PrepRequest { 219 iovecs := bytes2iovec(bs) 220 221 var bp unsafe.Pointer 222 if len(iovecs) > 0 { 223 bp = unsafe.Pointer(&iovecs[0]) 224 } else { 225 bp = unsafe.Pointer(&_zero) 226 } 227 228 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 229 userData.request.resolver = fdResolver 230 userData.SetRequestBuffers(bs) 231 232 sqe.PrepOperation( 233 iouring_syscall.IORING_OP_WRITEV, 234 int32(fd), 235 uint64(uintptr(bp)), 236 uint32(len(iovecs)), 237 0, 238 ) 239 } 240 } 241 242 func Pwritev(fd int, bs [][]byte, offset int64) PrepRequest { 243 iovecs := bytes2iovec(bs) 244 245 var bp unsafe.Pointer 246 if len(iovecs) > 0 { 247 bp = unsafe.Pointer(&iovecs[0]) 248 } else { 249 bp = unsafe.Pointer(&_zero) 250 } 251 252 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 253 userData.request.resolver = fdResolver 254 userData.SetRequestBuffers(bs) 255 256 sqe.PrepOperation( 257 iouring_syscall.IORING_OP_WRITEV, 258 int32(fd), 259 uint64(uintptr(bp)), 260 uint32(len(iovecs)), 261 uint64(offset), 262 ) 263 } 264 } 265 266 func Send(sockfd int, b []byte, flags int) PrepRequest { 267 var bp unsafe.Pointer 268 if len(b) > 0 { 269 bp = unsafe.Pointer(&b[0]) 270 } else { 271 bp = unsafe.Pointer(&_zero) 272 } 273 274 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 275 userData.SetRequestBuffer(b, nil) 276 277 sqe.PrepOperation( 278 iouring_syscall.IORING_OP_SEND, 279 int32(sockfd), 280 uint64(uintptr(bp)), 281 uint32(len(b)), 282 0, 283 ) 284 sqe.SetOpFlags(uint32(flags)) 285 } 286 } 287 288 func Recv(sockfd int, b []byte, flags int) PrepRequest { 289 var bp unsafe.Pointer 290 if len(b) > 0 { 291 bp = unsafe.Pointer(&b[0]) 292 } else { 293 bp = unsafe.Pointer(&_zero) 294 } 295 296 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 297 userData.SetRequestBuffer(b, nil) 298 299 sqe.PrepOperation( 300 iouring_syscall.IORING_OP_RECV, 301 int32(sockfd), 302 uint64(uintptr(bp)), 303 uint32(len(b)), 304 0, 305 ) 306 sqe.SetOpFlags(uint32(flags)) 307 } 308 } 309 310 func Sendmsg(sockfd int, p, oob []byte, to syscall.Sockaddr, flags int) (PrepRequest, error) { 311 var ptr unsafe.Pointer 312 var salen uint32 313 if to != nil { 314 var err error 315 ptr, salen, err = sockaddr(to) 316 if err != nil { 317 return nil, err 318 } 319 } 320 321 msg := &syscall.Msghdr{} 322 msg.Name = (*byte)(ptr) 323 msg.Namelen = uint32(salen) 324 var iov syscall.Iovec 325 if len(p) > 0 { 326 iov.Base = &p[0] 327 iov.SetLen(len(p)) 328 } 329 var dummy byte 330 if len(oob) > 0 { 331 if len(p) == 0 { 332 var sockType int 333 sockType, err := syscall.GetsockoptInt(sockfd, syscall.SOL_SOCKET, syscall.SO_TYPE) 334 if err != nil { 335 return nil, err 336 } 337 // send at least one normal byte 338 if sockType != syscall.SOCK_DGRAM { 339 iov.Base = &dummy 340 iov.SetLen(1) 341 } 342 } 343 msg.Control = &oob[0] 344 msg.SetControllen(len(oob)) 345 } 346 msg.Iov = &iov 347 msg.Iovlen = 1 348 349 resolver := func(req Request) { 350 result := req.(*request) 351 result.r0 = int(result.res) 352 errResolver(result) 353 if result.err != nil { 354 return 355 } 356 357 if len(oob) > 0 && len(p) == 0 { 358 result.r0 = 0 359 } 360 } 361 362 msgptr := unsafe.Pointer(msg) 363 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 364 userData.hold(msg, to) 365 userData.request.resolver = resolver 366 userData.SetRequestBuffer(p, oob) 367 368 sqe.PrepOperation(iouring_syscall.IORING_OP_SENDMSG, int32(sockfd), uint64(uintptr(msgptr)), 1, 0) 369 sqe.SetOpFlags(uint32(flags)) 370 }, nil 371 } 372 373 func Recvmsg(sockfd int, p, oob []byte, to syscall.Sockaddr, flags int) (PrepRequest, error) { 374 var msg syscall.Msghdr 375 var rsa syscall.RawSockaddrAny 376 msg.Name = (*byte)(unsafe.Pointer(&rsa)) 377 msg.Namelen = uint32(syscall.SizeofSockaddrAny) 378 var iov syscall.Iovec 379 if len(p) > 0 { 380 iov.Base = &p[0] 381 iov.SetLen(len(p)) 382 } 383 var dummy byte 384 if len(oob) > 0 { 385 if len(p) == 0 { 386 var sockType int 387 sockType, err := syscall.GetsockoptInt(sockfd, syscall.SOL_SOCKET, syscall.SO_TYPE) 388 if err != nil { 389 return nil, err 390 } 391 // receive at least one normal byte 392 if sockType != syscall.SOCK_DGRAM { 393 iov.Base = &dummy 394 iov.SetLen(1) 395 } 396 } 397 msg.Control = &oob[0] 398 msg.SetControllen(len(oob)) 399 } 400 msg.Iov = &iov 401 msg.Iovlen = 1 402 403 resolver := func(req Request) { 404 result := req.(*request) 405 result.r0 = int(result.res) 406 errResolver(result) 407 if result.err != nil { 408 return 409 } 410 411 if len(oob) > 0 && len(p) == 0 { 412 result.r0 = 0 413 } 414 } 415 416 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 417 userData.hold(&msg, &rsa) 418 userData.request.resolver = resolver 419 userData.SetRequestBuffer(p, oob) 420 421 sqe.PrepOperation( 422 iouring_syscall.IORING_OP_RECVMSG, 423 int32(sockfd), 424 uint64(uintptr(unsafe.Pointer(&msg))), 425 1, 426 0, 427 ) 428 sqe.SetOpFlags(uint32(flags)) 429 }, nil 430 } 431 432 func Accept(sockfd int) PrepRequest { 433 var rsa syscall.RawSockaddrAny 434 var len uint32 = syscall.SizeofSockaddrAny 435 436 resolver := func(req Request) { 437 result := req.(*request) 438 fd := int(result.res) 439 errResolver(result) 440 if result.err != nil { 441 return 442 } 443 444 result.r0 = fd 445 result.r1, result.err = anyToSockaddr(&rsa) 446 if result.err != nil { 447 syscall.Close(fd) 448 result.r0 = 0 449 } 450 } 451 452 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 453 userData.hold(&len) 454 userData.request.resolver = resolver 455 sqe.PrepOperation(iouring_syscall.IORING_OP_ACCEPT, int32(sockfd), uint64(uintptr(unsafe.Pointer(&rsa))), 0, uint64(uintptr(unsafe.Pointer(&len)))) 456 } 457 } 458 459 func Accept4(sockfd int, flags int) PrepRequest { 460 var rsa syscall.RawSockaddrAny 461 var len uint32 = syscall.SizeofSockaddrAny 462 463 resolver := func(req Request) { 464 result := req.(*request) 465 fd := int(result.res) 466 errResolver(result) 467 if result.err != nil { 468 return 469 } 470 471 if len > syscall.SizeofSockaddrAny { 472 panic("RawSockaddrAny too small") 473 } 474 475 result.r0 = fd 476 result.r1, result.err = anyToSockaddr(&rsa) 477 if result.err != nil { 478 syscall.Close(fd) 479 result.r0 = 0 480 } 481 } 482 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 483 userData.hold(&rsa, &len) 484 userData.request.resolver = resolver 485 486 sqe.PrepOperation( 487 iouring_syscall.IORING_OP_ACCEPT, 488 int32(sockfd), 489 uint64(uintptr(unsafe.Pointer(&rsa))), 490 0, 491 uint64(uintptr(unsafe.Pointer(&len))), 492 ) 493 sqe.SetOpFlags(uint32(flags)) 494 } 495 } 496 497 func Connect(sockfd int, sa syscall.Sockaddr) (PrepRequest, error) { 498 ptr, n, err := sockaddr(sa) 499 if err != nil { 500 return nil, err 501 } 502 503 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 504 userData.hold(sa) 505 userData.request.resolver = errResolver 506 507 sqe.PrepOperation( 508 iouring_syscall.IORING_OP_CONNECT, 509 int32(sockfd), 510 uint64(uintptr(ptr)), 511 0, 512 uint64(n), 513 ) 514 }, nil 515 } 516 517 func Openat(dirfd int, path string, flags uint32, mode uint32) (PrepRequest, error) { 518 flags |= syscall.O_LARGEFILE 519 b, err := syscall.ByteSliceFromString(path) 520 if err != nil { 521 return nil, err 522 } 523 524 bp := unsafe.Pointer(&b[0]) 525 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 526 userData.hold(&b) 527 userData.request.resolver = fdResolver 528 529 sqe.PrepOperation( 530 iouring_syscall.IORING_OP_OPENAT, 531 int32(dirfd), 532 uint64(uintptr(bp)), 533 mode, 534 0, 535 ) 536 sqe.SetOpFlags(flags) 537 }, nil 538 } 539 540 func Openat2(dirfd int, path string, how *unix.OpenHow) (PrepRequest, error) { 541 b, err := syscall.ByteSliceFromString(path) 542 if err != nil { 543 return nil, err 544 } 545 546 bp := unsafe.Pointer(&b[0]) 547 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 548 userData.hold(&b) 549 userData.request.resolver = fdResolver 550 551 sqe.PrepOperation( 552 iouring_syscall.IORING_OP_OPENAT2, 553 int32(dirfd), 554 uint64(uintptr(bp)), 555 unix.SizeofOpenHow, 556 uint64(uintptr(unsafe.Pointer(how))), 557 ) 558 }, nil 559 } 560 561 func Statx(dirfd int, path string, flags uint32, mask int, stat *unix.Statx_t) (PrepRequest, error) { 562 b, err := syscall.ByteSliceFromString(path) 563 if err != nil { 564 return nil, err 565 } 566 567 bp := unsafe.Pointer(&b[0]) 568 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 569 userData.request.resolver = errResolver 570 userData.hold(&b, stat) 571 572 sqe.PrepOperation( 573 iouring_syscall.IORING_OP_STATX, 574 int32(dirfd), 575 uint64(uintptr(bp)), 576 uint32(mask), 577 uint64(uintptr(unsafe.Pointer(stat))), 578 ) 579 sqe.SetOpFlags(flags) 580 }, nil 581 } 582 583 func Fsync(fd int) PrepRequest { 584 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 585 userData.request.resolver = errResolver 586 sqe.PrepOperation(iouring_syscall.IORING_OP_FSYNC, int32(fd), 0, 0, 0) 587 } 588 } 589 590 func Fdatasync(fd int) PrepRequest { 591 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 592 userData.request.resolver = errResolver 593 sqe.PrepOperation(iouring_syscall.IORING_OP_FSYNC, int32(fd), 0, 0, 0) 594 sqe.SetOpFlags(iouring_syscall.IORING_FSYNC_DATASYNC) 595 } 596 } 597 598 func Fallocate(fd int, mode uint32, off int64, length int64) PrepRequest { 599 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 600 userData.request.resolver = errResolver 601 602 sqe.PrepOperation( 603 iouring_syscall.IORING_OP_FALLOCATE, 604 int32(fd), 605 uint64(length), 606 uint32(mode), 607 uint64(off), 608 ) 609 } 610 } 611 612 func Close(fd int) PrepRequest { 613 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 614 userData.request.resolver = errResolver 615 sqe.PrepOperation(iouring_syscall.IORING_OP_CLOSE, int32(fd), 0, 0, 0) 616 } 617 } 618 619 func Madvise(b []byte, advice int) PrepRequest { 620 var bp unsafe.Pointer 621 if len(b) > 0 { 622 bp = unsafe.Pointer(&b[0]) 623 } else { 624 bp = unsafe.Pointer(&_zero) 625 } 626 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 627 userData.request.resolver = errResolver 628 userData.SetRequestBuffer(b, nil) 629 630 sqe.PrepOperation( 631 iouring_syscall.IORING_OP_MADVISE, 632 -1, 633 uint64(uintptr(bp)), 634 uint32(len(b)), 635 0, 636 ) 637 sqe.SetOpFlags(uint32(advice)) 638 } 639 } 640 641 func EpollCtl(epfd int, op int, fd int, event *syscall.EpollEvent) PrepRequest { 642 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 643 userData.request.resolver = errResolver 644 645 sqe.PrepOperation( 646 iouring_syscall.IORING_OP_EPOLL_CTL, 647 int32(epfd), 648 uint64(uintptr(unsafe.Pointer(event))), 649 uint32(op), 650 uint64(fd), 651 ) 652 } 653 } 654 655 func Mkdirat(dirFd int, path string, mode uint32) (PrepRequest, error) { 656 b, err := syscall.ByteSliceFromString(path) 657 if err != nil { 658 return nil, err 659 } 660 661 bp := unsafe.Pointer(&b[0]) 662 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 663 userData.hold(&b) 664 userData.request.resolver = fdResolver 665 666 sqe.PrepOperation( 667 iouring_syscall.IORING_OP_MKDIRAT, 668 int32(dirFd), 669 uint64(uintptr(bp)), 670 mode, 671 0, 672 ) 673 }, nil 674 } 675 676 func Unlinkat(fd int, path string, flags int32) (PrepRequest, error) { 677 b, err := syscall.ByteSliceFromString(path) 678 if err != nil { 679 return nil, err 680 } 681 682 bp := unsafe.Pointer(&b[0]) 683 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 684 userData.hold(&b) 685 userData.request.resolver = fdResolver 686 687 sqe.PrepOperation( 688 iouring_syscall.IORING_OP_UNLINKAT, 689 int32(fd), 690 uint64(uintptr(bp)), 691 0, 692 0, 693 ) 694 sqe.SetOpFlags(uint32(flags)) 695 }, nil 696 } 697 698 func Symlinkat(target string, newDirFd int, linkPath string) (PrepRequest, error) { 699 bTarget, err := syscall.ByteSliceFromString(target) 700 if err != nil { 701 return nil, err 702 } 703 bLink, err := syscall.ByteSliceFromString(linkPath) 704 if err != nil { 705 return nil, err 706 } 707 708 bpTarget := unsafe.Pointer(&bTarget[0]) 709 bpLink := unsafe.Pointer(&bLink[0]) 710 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 711 userData.hold(&bTarget, &bLink) 712 userData.request.resolver = fdResolver 713 714 sqe.PrepOperation( 715 iouring_syscall.IORING_OP_SYMLINKAT, 716 int32(newDirFd), 717 uint64(uintptr(bpTarget)), 718 0, 719 uint64(uintptr(bpLink)), 720 ) 721 }, nil 722 } 723 724 func Renameat2(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (PrepRequest, error) { 725 bOldPath, err := syscall.ByteSliceFromString(oldPath) 726 if err != nil { 727 return nil, err 728 } 729 bNewPath, err := syscall.ByteSliceFromString(newPath) 730 if err != nil { 731 return nil, err 732 } 733 734 bpOldPath := unsafe.Pointer(&bOldPath[0]) 735 bpNewPath := unsafe.Pointer(&bNewPath[0]) 736 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 737 userData.hold(&bOldPath, &bNewPath) 738 userData.request.resolver = fdResolver 739 740 sqe.PrepOperation( 741 iouring_syscall.IORING_OP_RENAMEAT, 742 int32(oldDirFd), uint64(uintptr(bpOldPath)), 743 uint32(newDirFd), uint64(uintptr(bpNewPath)), 744 ) 745 sqe.SetOpFlags(uint32(flags)) 746 }, nil 747 } 748 749 func Renameat(oldDirFd int, oldPath string, newDirFd int, newPath string) (PrepRequest, error) { 750 return Renameat2(oldDirFd, oldPath, newDirFd, newPath, 0) 751 } 752 753 func Linkat(targetDirFd int, targetPath string, linkDirFd int, linkPath string, flags int) (PrepRequest, error) { 754 bTargetPath, err := syscall.ByteSliceFromString(targetPath) 755 if err != nil { 756 return nil, err 757 } 758 bLinkPath, err := syscall.ByteSliceFromString(linkPath) 759 if err != nil { 760 return nil, err 761 } 762 763 bpTargetPath := unsafe.Pointer(&bTargetPath[0]) 764 bpLinkPath := unsafe.Pointer(&bLinkPath[0]) 765 return func(sqe iouring_syscall.SubmissionQueueEntry, userData *UserData) { 766 userData.hold(&bpTargetPath, &bpLinkPath) 767 userData.request.resolver = fdResolver 768 769 sqe.PrepOperation( 770 iouring_syscall.IORING_OP_LINKAT, 771 int32(targetDirFd), 772 uint64(uintptr(bpTargetPath)), 773 uint32(linkDirFd), 774 uint64(uintptr(bpLinkPath)), 775 ) 776 sqe.SetOpFlags(uint32(flags)) 777 }, nil 778 }