github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/lisafs/message.go (about) 1 // Copyright 2021 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package lisafs 16 17 import ( 18 "fmt" 19 "math" 20 "os" 21 "strings" 22 23 "github.com/nicocha30/gvisor-ligolo/pkg/abi/linux" 24 "github.com/nicocha30/gvisor-ligolo/pkg/hostarch" 25 "github.com/nicocha30/gvisor-ligolo/pkg/marshal/primitive" 26 ) 27 28 // Messages have two parts: 29 // * A transport header used to decipher received messages. 30 // * A byte array referred to as "payload" which contains the actual message. 31 // "dataLen" refers to the size of both combined. 32 // 33 // All messages must implement the following functions: 34 // * marshal.Marshallable.SizeBytes 35 // * marshal.Marshallable.Marshal{Unsafe/Bytes} 36 // * marshal.CheckedMarshallable.CheckedUnmarshal 37 // * fmt.Stringer.String 38 // 39 // There is no explicit interface definition for this because that definition 40 // will not be used anywhere. If a concrete type is passed into a function 41 // which receives it as an interface, the struct is moved to the heap. This 42 // erodes memory performance. Message structs are be short lived - they are 43 // initialized, marshalled into a buffer and not used after that. So heap 44 // allocating these message structs is wasteful. Don't define Message interface 45 // so it's not used. Instead use function arguments. See Client.SndRcvMessage. 46 // 47 // Unmarshalling code should use the Checked variant of the Unmarshal functions 48 // because a malicious encoder could have manipulated payload bytes to make the 49 // unchecked unmarshal variants panic due to the lack of bound checking. 50 // Marshalling code does not need additional bound checking because the caller 51 // itself intializes the struct being marshalled, so it is trusted. 52 // 53 // String() implementations must ensure that the message struct doesn't escape. 54 // For instance, directly passing the struct to fmt.Sprintf() escapes it 55 // because of the implicit conversion to any. 56 57 type marshalFunc func([]byte) []byte 58 type unmarshalFunc func([]byte) ([]byte, bool) 59 type debugStringer func() string 60 61 // MID (message ID) is used to identify messages to parse from payload. 62 // 63 // +marshal slice:MIDSlice 64 type MID uint16 65 66 // These constants are used to identify their corresponding message types. 67 const ( 68 // Error is only used in responses to pass errors to client. 69 Error MID = 0 70 71 // Mount is used to establish connection between the client and server mount 72 // point. lisafs requires that the client makes a successful Mount RPC before 73 // making other RPCs. 74 Mount MID = 1 75 76 // Channel requests to start a new communicational channel. 77 Channel MID = 2 78 79 // FStat requests the stat(2) results for a specified file. 80 FStat MID = 3 81 82 // SetStat requests to change file attributes. Note that there is no one 83 // corresponding Linux syscall. This is a conglomeration of fchmod(2), 84 // fchown(2), ftruncate(2) and futimesat(2). 85 SetStat MID = 4 86 87 // Walk requests to walk the specified path starting from the specified 88 // directory. Server-side path traversal is terminated preemptively on 89 // symlinks entries because they can cause non-linear traversal. 90 Walk MID = 5 91 92 // WalkStat is the same as Walk, except the following differences: 93 // * If the first path component is "", then it also returns stat results 94 // for the directory where the walk starts. 95 // * Does not return Inode, just the Stat results for each path component. 96 WalkStat MID = 6 97 98 // OpenAt is analogous to openat(2). It does not perform any walk. It merely 99 // duplicates the control FD with the open flags passed. 100 OpenAt MID = 7 101 102 // OpenCreateAt is analogous to openat(2) with O_CREAT|O_EXCL added to flags. 103 // It also returns the newly created file inode. 104 OpenCreateAt MID = 8 105 106 // Close is analogous to close(2) but can work on multiple FDs. 107 Close MID = 9 108 109 // FSync is analogous to fsync(2) but can work on multiple FDs. 110 FSync MID = 10 111 112 // PWrite is analogous to pwrite(2). 113 PWrite MID = 11 114 115 // PRead is analogous to pread(2). 116 PRead MID = 12 117 118 // MkdirAt is analogous to mkdirat(2). 119 MkdirAt MID = 13 120 121 // MknodAt is analogous to mknodat(2). 122 MknodAt MID = 14 123 124 // SymlinkAt is analogous to symlinkat(2). 125 SymlinkAt MID = 15 126 127 // LinkAt is analogous to linkat(2). 128 LinkAt MID = 16 129 130 // FStatFS is analogous to fstatfs(2). 131 FStatFS MID = 17 132 133 // FAllocate is analogous to fallocate(2). 134 FAllocate MID = 18 135 136 // ReadLinkAt is analogous to readlinkat(2). 137 ReadLinkAt MID = 19 138 139 // Flush cleans up the file state. Its behavior is implementation 140 // dependent and might not even be supported in server implementations. 141 Flush MID = 20 142 143 // Connect is loosely analogous to connect(2). 144 Connect MID = 21 145 146 // UnlinkAt is analogous to unlinkat(2). 147 UnlinkAt MID = 22 148 149 // RenameAt is loosely analogous to renameat(2). 150 RenameAt MID = 23 151 152 // Getdents64 is analogous to getdents64(2). 153 Getdents64 MID = 24 154 155 // FGetXattr is analogous to fgetxattr(2). 156 FGetXattr MID = 25 157 158 // FSetXattr is analogous to fsetxattr(2). 159 FSetXattr MID = 26 160 161 // FListXattr is analogous to flistxattr(2). 162 FListXattr MID = 27 163 164 // FRemoveXattr is analogous to fremovexattr(2). 165 FRemoveXattr MID = 28 166 167 // BindAt is analogous to bind(2). 168 BindAt MID = 29 169 170 // Listen is analogous to listen(2). 171 Listen MID = 30 172 173 // Accept is analogous to accept4(2). 174 Accept MID = 31 175 ) 176 177 const ( 178 // NoUID is a sentinel used to indicate no valid UID. 179 NoUID UID = math.MaxUint32 180 181 // NoGID is a sentinel used to indicate no valid GID. 182 NoGID GID = math.MaxUint32 183 ) 184 185 // MaxMessageSize is the recommended max message size that can be used by 186 // connections. Server implementations may choose to use other values. 187 func MaxMessageSize() uint32 { 188 // Return HugePageSize - PageSize so that when flipcall packet window is 189 // created with MaxMessageSize() + flipcall header size + channel header 190 // size, HugePageSize is allocated and can be backed by a single huge page 191 // if supported by the underlying memfd. 192 return uint32(hostarch.HugePageSize - os.Getpagesize()) 193 } 194 195 // UID represents a user ID. 196 // 197 // +marshal 198 type UID uint32 199 200 // Ok returns true if uid is not NoUID. 201 func (uid UID) Ok() bool { 202 return uid != NoUID 203 } 204 205 // GID represents a group ID. 206 // 207 // +marshal 208 type GID uint32 209 210 // Ok returns true if gid is not NoGID. 211 func (gid GID) Ok() bool { 212 return gid != NoGID 213 } 214 215 // EmptyMessage is an empty message. 216 type EmptyMessage struct{} 217 218 // String implements fmt.Stringer.String. 219 func (*EmptyMessage) String() string { 220 return "EmptyMessage{}" 221 } 222 223 // SizeBytes implements marshal.Marshallable.SizeBytes. 224 func (*EmptyMessage) SizeBytes() int { 225 return 0 226 } 227 228 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 229 func (*EmptyMessage) MarshalBytes(dst []byte) []byte { return dst } 230 231 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 232 func (*EmptyMessage) CheckedUnmarshal(src []byte) ([]byte, bool) { return src, true } 233 234 // SizedString represents a string in memory. The marshalled string bytes are 235 // preceded by a uint16 signifying the string length. 236 type SizedString string 237 238 // SizeBytes implements marshal.Marshallable.SizeBytes. 239 func (s *SizedString) SizeBytes() int { 240 return (*primitive.Uint16)(nil).SizeBytes() + len(*s) 241 } 242 243 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 244 func (s *SizedString) MarshalBytes(dst []byte) []byte { 245 strLen := primitive.Uint16(len(*s)) 246 dst = strLen.MarshalUnsafe(dst) 247 // Copy without any allocation. 248 return dst[copy(dst[:strLen], *s):] 249 } 250 251 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 252 func (s *SizedString) CheckedUnmarshal(src []byte) ([]byte, bool) { 253 var strLen primitive.Uint16 254 srcRemain, ok := strLen.CheckedUnmarshal(src) 255 if !ok || len(srcRemain) < int(strLen) { 256 return src, false 257 } 258 // Take the hit, this leads to an allocation + memcpy. No way around it. 259 *s = SizedString(srcRemain[:strLen]) 260 return srcRemain[strLen:], true 261 } 262 263 // StringArray represents an array of SizedStrings in memory. The marshalled 264 // array data is preceded by a uint16 signifying the array length. 265 type StringArray []string 266 267 // String implements fmt.Stringer.String. This ensures that the string slice is 268 // not escaped so that callers that use a statically sized string array do not 269 // incur an unnecessary allocation. 270 func (s *StringArray) String() string { 271 var b strings.Builder 272 b.WriteString("[") 273 b.WriteString(strings.Join(*s, ", ")) 274 b.WriteString("]") 275 return b.String() 276 } 277 278 // SizeBytes implements marshal.Marshallable.SizeBytes. 279 func (s *StringArray) SizeBytes() int { 280 size := (*primitive.Uint16)(nil).SizeBytes() 281 for _, str := range *s { 282 sstr := SizedString(str) 283 size += sstr.SizeBytes() 284 } 285 return size 286 } 287 288 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 289 func (s *StringArray) MarshalBytes(dst []byte) []byte { 290 arrLen := primitive.Uint16(len(*s)) 291 dst = arrLen.MarshalUnsafe(dst) 292 for _, str := range *s { 293 sstr := SizedString(str) 294 dst = sstr.MarshalBytes(dst) 295 } 296 return dst 297 } 298 299 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 300 func (s *StringArray) CheckedUnmarshal(src []byte) ([]byte, bool) { 301 var arrLen primitive.Uint16 302 srcRemain, ok := arrLen.CheckedUnmarshal(src) 303 if !ok { 304 return src, false 305 } 306 307 if cap(*s) < int(arrLen) { 308 *s = make([]string, arrLen) 309 } else { 310 *s = (*s)[:arrLen] 311 } 312 313 for i := primitive.Uint16(0); i < arrLen; i++ { 314 var sstr SizedString 315 srcRemain, ok = sstr.CheckedUnmarshal(srcRemain) 316 if !ok { 317 return src, false 318 } 319 (*s)[i] = string(sstr) 320 } 321 return srcRemain, true 322 } 323 324 // Inode represents an inode on the remote filesystem. 325 // 326 // +marshal slice:InodeSlice 327 type Inode struct { 328 ControlFD FDID 329 Stat linux.Statx 330 } 331 332 func (i *Inode) String() string { 333 return fmt.Sprintf("Inode{ControlFD: %d, Stat: %s}", i.ControlFD, i.Stat.String()) 334 } 335 336 // MountReq is an empty request to Mount on the connection. 337 type MountReq struct{ EmptyMessage } 338 339 // String implements fmt.Stringer.String. 340 func (*MountReq) String() string { 341 return "MountReq{}" 342 } 343 344 // MountResp represents a Mount response. 345 type MountResp struct { 346 Root Inode 347 // MaxMessageSize is the maximum size of messages communicated between the 348 // client and server in bytes. This includes the communication header. 349 MaxMessageSize primitive.Uint32 350 // SupportedMs holds all the supported messages. 351 SupportedMs []MID 352 } 353 354 // String implements fmt.Stringer.String. 355 func (m *MountResp) String() string { 356 return fmt.Sprintf("MountResp{Root: %s, MaxMessageSize: %d, SupportedMs: %+v}", m.Root.String(), m.MaxMessageSize, m.SupportedMs) 357 } 358 359 // SizeBytes implements marshal.Marshallable.SizeBytes. 360 func (m *MountResp) SizeBytes() int { 361 return m.Root.SizeBytes() + 362 m.MaxMessageSize.SizeBytes() + 363 (*primitive.Uint16)(nil).SizeBytes() + 364 (len(m.SupportedMs) * (*MID)(nil).SizeBytes()) 365 } 366 367 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 368 func (m *MountResp) MarshalBytes(dst []byte) []byte { 369 dst = m.Root.MarshalUnsafe(dst) 370 dst = m.MaxMessageSize.MarshalUnsafe(dst) 371 numSupported := primitive.Uint16(len(m.SupportedMs)) 372 dst = numSupported.MarshalBytes(dst) 373 return MarshalUnsafeMIDSlice(m.SupportedMs, dst) 374 } 375 376 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 377 func (m *MountResp) CheckedUnmarshal(src []byte) ([]byte, bool) { 378 m.SupportedMs = m.SupportedMs[:0] 379 if m.SizeBytes() > len(src) { 380 return src, false 381 } 382 srcRemain := m.Root.UnmarshalUnsafe(src) 383 srcRemain = m.MaxMessageSize.UnmarshalUnsafe(srcRemain) 384 var numSupported primitive.Uint16 385 srcRemain = numSupported.UnmarshalBytes(srcRemain) 386 if int(numSupported)*(*MID)(nil).SizeBytes() > len(srcRemain) { 387 return src, false 388 } 389 if cap(m.SupportedMs) < int(numSupported) { 390 m.SupportedMs = make([]MID, numSupported) 391 } else { 392 m.SupportedMs = m.SupportedMs[:numSupported] 393 } 394 return UnmarshalUnsafeMIDSlice(m.SupportedMs, srcRemain), true 395 } 396 397 // ChannelReq is an empty requent to create a Channel. 398 type ChannelReq struct{ EmptyMessage } 399 400 // String implements fmt.Stringer.String. 401 func (*ChannelReq) String() string { 402 return "ChannelReq{}" 403 } 404 405 // ChannelResp is the response to the create channel request. 406 // 407 // +marshal boundCheck 408 type ChannelResp struct { 409 dataOffset int64 410 dataLength uint64 411 } 412 413 // String implements fmt.Stringer.String. 414 func (c *ChannelResp) String() string { 415 return fmt.Sprintf("ChannelResp{dataOffset: %d, dataLength: %d}", c.dataOffset, c.dataLength) 416 } 417 418 // ErrorResp is returned to represent an error while handling a request. 419 // 420 // +marshal 421 type ErrorResp struct { 422 errno uint32 423 } 424 425 // String implements fmt.Stringer.String. 426 func (e *ErrorResp) String() string { 427 return fmt.Sprintf("ErrorResp{errno: %d}", e.errno) 428 } 429 430 // StatReq requests the stat results for the specified FD. 431 // 432 // +marshal boundCheck 433 type StatReq struct { 434 FD FDID 435 } 436 437 // String implements fmt.Stringer.String. 438 func (s *StatReq) String() string { 439 return fmt.Sprintf("StatReq{FD: %d}", s.FD) 440 } 441 442 // SetStatReq is used to set attributeds on FDs. 443 // 444 // +marshal boundCheck 445 type SetStatReq struct { 446 FD FDID 447 Mask uint32 448 Mode uint32 // Only permissions part is settable. 449 UID UID 450 GID GID 451 Size uint64 452 Atime linux.Timespec 453 Mtime linux.Timespec 454 } 455 456 // String implements fmt.Stringer.String. 457 func (s *SetStatReq) String() string { 458 return fmt.Sprintf("SetStatReq{FD: %d, Mask: %#x, Mode: %d, UID: %d, GID: %d, Size: %d, Atime: %s, Mtime: %s}", 459 s.FD, s.Mask, s.Mode, s.UID, s.GID, s.Size, s.Atime.ToTime(), s.Mtime.ToTime()) 460 } 461 462 // SetStatResp is used to communicate SetStat results. It contains a mask 463 // representing the failed changes. It also contains the errno of the failed 464 // set attribute operation. If multiple operations failed then any of those 465 // errnos can be returned. 466 // 467 // +marshal boundCheck 468 type SetStatResp struct { 469 FailureMask uint32 470 FailureErrNo uint32 471 } 472 473 // String implements fmt.Stringer.String. 474 func (s *SetStatResp) String() string { 475 return fmt.Sprintf("SetStatResp{FailureMask: %#x, FailureErrNo: %d}", s.FailureMask, s.FailureErrNo) 476 } 477 478 // WalkReq is used to request to walk multiple path components at once. This 479 // is used for both Walk and WalkStat. 480 type WalkReq struct { 481 DirFD FDID 482 Path StringArray 483 } 484 485 // String implements fmt.Stringer.String. 486 func (w *WalkReq) String() string { 487 return fmt.Sprintf("WalkReq{DirFD: %d, Path: %s}", w.DirFD, w.Path.String()) 488 } 489 490 // SizeBytes implements marshal.Marshallable.SizeBytes. 491 func (w *WalkReq) SizeBytes() int { 492 return w.DirFD.SizeBytes() + w.Path.SizeBytes() 493 } 494 495 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 496 func (w *WalkReq) MarshalBytes(dst []byte) []byte { 497 dst = w.DirFD.MarshalUnsafe(dst) 498 return w.Path.MarshalBytes(dst) 499 } 500 501 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 502 func (w *WalkReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 503 w.Path = w.Path[:0] 504 if w.SizeBytes() > len(src) { 505 return src, false 506 } 507 srcRemain := w.DirFD.UnmarshalUnsafe(src) 508 if srcRemain, ok := w.Path.CheckedUnmarshal(srcRemain); ok { 509 return srcRemain, true 510 } 511 return src, false 512 } 513 514 // WalkStatus is used to indicate the reason for partial/unsuccessful server 515 // side Walk operations. Please note that partial/unsuccessful walk operations 516 // do not necessarily fail the RPC. The RPC is successful with a failure hint 517 // which can be used by the client to infer server-side state. 518 type WalkStatus = primitive.Uint8 519 520 const ( 521 // WalkSuccess indicates that all path components were successfully walked. 522 WalkSuccess WalkStatus = iota 523 524 // WalkComponentDoesNotExist indicates that the walk was prematurely 525 // terminated because an intermediate path component does not exist on 526 // server. The results of all previous existing path components is returned. 527 WalkComponentDoesNotExist 528 529 // WalkComponentSymlink indicates that the walk was prematurely 530 // terminated because an intermediate path component was a symlink. It is not 531 // safe to resolve symlinks remotely (unaware of mount points). 532 WalkComponentSymlink 533 ) 534 535 func walkStatusToString(ws WalkStatus) string { 536 switch ws { 537 case WalkSuccess: 538 return "Success" 539 case WalkComponentDoesNotExist: 540 return "ComponentDoesNotExist" 541 case WalkComponentSymlink: 542 return "ComponentSymlink" 543 default: 544 panic(fmt.Sprintf("Unknown WalkStatus: %d", ws)) 545 } 546 } 547 548 // WalkResp is used to communicate the inodes walked by the server. In memory, 549 // the inode array is preceded by a uint16 integer denoting array length. 550 type WalkResp struct { 551 Status WalkStatus 552 Inodes []Inode 553 } 554 555 // String implements fmt.Stringer.String. This ensures that the Inode slice is 556 // not escaped so that callers that use a statically sized Inode array do not 557 // incur an unnecessary allocation. 558 func (w *WalkResp) String() string { 559 var arrB strings.Builder 560 arrB.WriteString("[") 561 for i := range w.Inodes { 562 if i > 0 { 563 arrB.WriteString(", ") 564 } 565 arrB.WriteString(w.Inodes[i].String()) 566 } 567 arrB.WriteString("]") 568 return fmt.Sprintf("WalkResp{Status: %s, Inodes: %s}", walkStatusToString(w.Status), arrB.String()) 569 } 570 571 // SizeBytes implements marshal.Marshallable.SizeBytes. 572 func (w *WalkResp) SizeBytes() int { 573 return w.Status.SizeBytes() + 574 (*primitive.Uint16)(nil).SizeBytes() + (len(w.Inodes) * (*Inode)(nil).SizeBytes()) 575 } 576 577 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 578 func (w *WalkResp) MarshalBytes(dst []byte) []byte { 579 dst = w.Status.MarshalUnsafe(dst) 580 581 numInodes := primitive.Uint16(len(w.Inodes)) 582 dst = numInodes.MarshalUnsafe(dst) 583 584 return MarshalUnsafeInodeSlice(w.Inodes, dst) 585 } 586 587 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 588 func (w *WalkResp) CheckedUnmarshal(src []byte) ([]byte, bool) { 589 w.Inodes = w.Inodes[:0] 590 if w.SizeBytes() > len(src) { 591 return src, false 592 } 593 srcRemain := w.Status.UnmarshalUnsafe(src) 594 595 var numInodes primitive.Uint16 596 srcRemain = numInodes.UnmarshalUnsafe(srcRemain) 597 if int(numInodes)*(*Inode)(nil).SizeBytes() > len(srcRemain) { 598 return src, false 599 } 600 if cap(w.Inodes) < int(numInodes) { 601 w.Inodes = make([]Inode, numInodes) 602 } else { 603 w.Inodes = w.Inodes[:numInodes] 604 } 605 return UnmarshalUnsafeInodeSlice(w.Inodes, srcRemain), true 606 } 607 608 // WalkStatResp is used to communicate stat results for WalkStat. In memory, 609 // the array data is preceded by a uint16 denoting the array length. 610 type WalkStatResp struct { 611 Stats []linux.Statx 612 } 613 614 // String implements fmt.Stringer.String. 615 func (w *WalkStatResp) String() string { 616 var arrB strings.Builder 617 arrB.WriteString("[") 618 for i := range w.Stats { 619 if i > 0 { 620 arrB.WriteString(", ") 621 } 622 arrB.WriteString(w.Stats[i].String()) 623 } 624 arrB.WriteString("]") 625 return fmt.Sprintf("WalkStatResp{Stats: %s}", arrB.String()) 626 } 627 628 // SizeBytes implements marshal.Marshallable.SizeBytes. 629 func (w *WalkStatResp) SizeBytes() int { 630 return (*primitive.Uint16)(nil).SizeBytes() + (len(w.Stats) * linux.SizeOfStatx) 631 } 632 633 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 634 func (w *WalkStatResp) MarshalBytes(dst []byte) []byte { 635 numStats := primitive.Uint16(len(w.Stats)) 636 dst = numStats.MarshalUnsafe(dst) 637 638 return linux.MarshalUnsafeStatxSlice(w.Stats, dst) 639 } 640 641 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 642 func (w *WalkStatResp) CheckedUnmarshal(src []byte) ([]byte, bool) { 643 w.Stats = w.Stats[:0] 644 if w.SizeBytes() > len(src) { 645 return src, false 646 } 647 var numStats primitive.Uint16 648 srcRemain := numStats.UnmarshalUnsafe(src) 649 650 if int(numStats)*linux.SizeOfStatx > len(srcRemain) { 651 return src, false 652 } 653 if cap(w.Stats) < int(numStats) { 654 w.Stats = make([]linux.Statx, numStats) 655 } else { 656 w.Stats = w.Stats[:numStats] 657 } 658 return linux.UnmarshalUnsafeStatxSlice(w.Stats, srcRemain), true 659 } 660 661 // OpenAtReq is used to open existing FDs with the specified flags. 662 // 663 // +marshal boundCheck 664 type OpenAtReq struct { 665 FD FDID 666 Flags uint32 667 _ uint32 // Need to make struct packed. 668 } 669 670 // String implements fmt.Stringer.String. 671 func (o *OpenAtReq) String() string { 672 return fmt.Sprintf("OpenAtReq{FD: %d, Flags: %#o}", o.FD, o.Flags) 673 } 674 675 // OpenAtResp is used to communicate the newly created FD. 676 // 677 // +marshal boundCheck 678 type OpenAtResp struct { 679 OpenFD FDID 680 } 681 682 // String implements fmt.Stringer.String. 683 func (o *OpenAtResp) String() string { 684 return fmt.Sprintf("OpenAtResp{OpenFD: %d}", o.OpenFD) 685 } 686 687 // +marshal 688 type createCommon struct { 689 DirFD FDID 690 UID UID 691 GID GID 692 Mode linux.FileMode 693 // The following are needed to make the struct packed. 694 _ uint16 695 _ uint32 696 } 697 698 // OpenCreateAtReq is used to make OpenCreateAt requests. 699 type OpenCreateAtReq struct { 700 createCommon 701 Flags primitive.Uint32 702 Name SizedString 703 } 704 705 // String implements fmt.Stringer.String. 706 func (o *OpenCreateAtReq) String() string { 707 return fmt.Sprintf("OpenCreateAtReq{DirFD: %d, Mode: %s, UID: %d, GID: %d, Flags: %#o, Name: %s}", o.DirFD, o.Mode, o.UID, o.GID, o.Flags, o.Name) 708 } 709 710 // SizeBytes implements marshal.Marshallable.SizeBytes. 711 func (o *OpenCreateAtReq) SizeBytes() int { 712 return o.createCommon.SizeBytes() + o.Flags.SizeBytes() + o.Name.SizeBytes() 713 } 714 715 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 716 func (o *OpenCreateAtReq) MarshalBytes(dst []byte) []byte { 717 dst = o.createCommon.MarshalUnsafe(dst) 718 dst = o.Flags.MarshalUnsafe(dst) 719 return o.Name.MarshalBytes(dst) 720 } 721 722 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 723 func (o *OpenCreateAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 724 o.Name = "" 725 if o.SizeBytes() > len(src) { 726 return src, false 727 } 728 srcRemain := o.createCommon.UnmarshalUnsafe(src) 729 srcRemain = o.Flags.UnmarshalUnsafe(srcRemain) 730 if srcRemain, ok := o.Name.CheckedUnmarshal(srcRemain); ok { 731 return srcRemain, true 732 } 733 return src, false 734 } 735 736 // OpenCreateAtResp is used to communicate successful OpenCreateAt results. 737 // 738 // +marshal boundCheck 739 type OpenCreateAtResp struct { 740 Child Inode 741 NewFD FDID 742 } 743 744 // String implements fmt.Stringer.String. 745 func (o *OpenCreateAtResp) String() string { 746 return fmt.Sprintf("OpenCreateAtResp{Child: %s, NewFD: %d}", o.Child.String(), o.NewFD) 747 } 748 749 // FdArray is a utility struct which implements a marshallable type for 750 // communicating an array of FDIDs. In memory, the array data is preceded by a 751 // uint16 denoting the array length. 752 type FdArray []FDID 753 754 // String implements fmt.Stringer.String. This ensures that the FDID slice is 755 // not escaped so that callers that use a statically sized FDID array do not 756 // incur an unnecessary allocation. 757 func (f *FdArray) String() string { 758 var b strings.Builder 759 b.WriteString("[") 760 for i, fd := range *f { 761 if i > 0 { 762 b.WriteString(", ") 763 } 764 b.WriteString(fmt.Sprintf("%d", fd)) 765 } 766 b.WriteString("]") 767 return b.String() 768 } 769 770 // SizeBytes implements marshal.Marshallable.SizeBytes. 771 func (f *FdArray) SizeBytes() int { 772 return (*primitive.Uint16)(nil).SizeBytes() + (len(*f) * (*FDID)(nil).SizeBytes()) 773 } 774 775 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 776 func (f *FdArray) MarshalBytes(dst []byte) []byte { 777 arrLen := primitive.Uint16(len(*f)) 778 dst = arrLen.MarshalUnsafe(dst) 779 return MarshalUnsafeFDIDSlice(*f, dst) 780 } 781 782 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 783 func (f *FdArray) CheckedUnmarshal(src []byte) ([]byte, bool) { 784 *f = (*f)[:0] 785 if f.SizeBytes() > len(src) { 786 return src, false 787 } 788 var arrLen primitive.Uint16 789 srcRemain := arrLen.UnmarshalUnsafe(src) 790 if int(arrLen)*(*FDID)(nil).SizeBytes() > len(srcRemain) { 791 return src, false 792 } 793 if cap(*f) < int(arrLen) { 794 *f = make(FdArray, arrLen) 795 } else { 796 *f = (*f)[:arrLen] 797 } 798 return UnmarshalUnsafeFDIDSlice(*f, srcRemain), true 799 } 800 801 // CloseReq is used to close(2) FDs. 802 type CloseReq struct { 803 FDs FdArray 804 } 805 806 // String implements fmt.Stringer.String. 807 func (c *CloseReq) String() string { 808 return fmt.Sprintf("CloseReq{FDs: %s}", c.FDs.String()) 809 } 810 811 // SizeBytes implements marshal.Marshallable.SizeBytes. 812 func (c *CloseReq) SizeBytes() int { 813 return c.FDs.SizeBytes() 814 } 815 816 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 817 func (c *CloseReq) MarshalBytes(dst []byte) []byte { 818 return c.FDs.MarshalBytes(dst) 819 } 820 821 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 822 func (c *CloseReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 823 return c.FDs.CheckedUnmarshal(src) 824 } 825 826 // CloseResp is an empty response to CloseReq. 827 type CloseResp struct{ EmptyMessage } 828 829 // String implements fmt.Stringer.String. 830 func (*CloseResp) String() string { 831 return "CloseResp{}" 832 } 833 834 // FsyncReq is used to fsync(2) FDs. 835 type FsyncReq struct { 836 FDs FdArray 837 } 838 839 // String implements fmt.Stringer.String. 840 func (f *FsyncReq) String() string { 841 return fmt.Sprintf("FsyncReq{FDs: %s}", f.FDs.String()) 842 } 843 844 // SizeBytes implements marshal.Marshallable.SizeBytes. 845 func (f *FsyncReq) SizeBytes() int { 846 return f.FDs.SizeBytes() 847 } 848 849 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 850 func (f *FsyncReq) MarshalBytes(dst []byte) []byte { 851 return f.FDs.MarshalBytes(dst) 852 } 853 854 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 855 func (f *FsyncReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 856 return f.FDs.CheckedUnmarshal(src) 857 } 858 859 // FsyncResp is an empty response to FsyncReq. 860 type FsyncResp struct{ EmptyMessage } 861 862 // String implements fmt.Stringer.String. 863 func (*FsyncResp) String() string { 864 return "FsyncResp{}" 865 } 866 867 // PReadReq is used to pread(2) on an FD. 868 // 869 // +marshal boundCheck 870 type PReadReq struct { 871 Offset uint64 872 FD FDID 873 Count uint32 874 _ uint32 // Need to make struct packed. 875 } 876 877 // String implements fmt.Stringer.String. 878 func (r *PReadReq) String() string { 879 return fmt.Sprintf("PReadReq{Offset: %d, FD: %d, Count: %d}", r.Offset, r.FD, r.Count) 880 } 881 882 // PReadResp is used to return the result of pread(2). 883 type PReadResp struct { 884 NumBytes primitive.Uint64 885 Buf []byte 886 } 887 888 // String implements fmt.Stringer.String. 889 func (r *PReadResp) String() string { 890 return fmt.Sprintf("PReadResp{NumBytes: %d, Buf: [...%d bytes...]}", r.NumBytes, len(r.Buf)) 891 } 892 893 // SizeBytes implements marshal.Marshallable.SizeBytes. 894 func (r *PReadResp) SizeBytes() int { 895 return r.NumBytes.SizeBytes() + int(r.NumBytes) 896 } 897 898 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 899 func (r *PReadResp) MarshalBytes(dst []byte) []byte { 900 dst = r.NumBytes.MarshalUnsafe(dst) 901 return dst[copy(dst[:r.NumBytes], r.Buf[:r.NumBytes]):] 902 } 903 904 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 905 func (r *PReadResp) CheckedUnmarshal(src []byte) ([]byte, bool) { 906 srcRemain, ok := r.NumBytes.CheckedUnmarshal(src) 907 if !ok || uint32(r.NumBytes) > uint32(len(srcRemain)) || uint32(r.NumBytes) > uint32(len(r.Buf)) { 908 return src, false 909 } 910 911 // We expect the client to have already allocated r.Buf. r.Buf probably 912 // (optimally) points to usermem. Directly copy into that. 913 r.Buf = r.Buf[:r.NumBytes] 914 return srcRemain[copy(r.Buf, srcRemain[:r.NumBytes]):], true 915 } 916 917 // PWriteReq is used to pwrite(2) on an FD. 918 type PWriteReq struct { 919 Offset primitive.Uint64 920 FD FDID 921 NumBytes primitive.Uint32 922 Buf []byte 923 } 924 925 // String implements fmt.Stringer.String. 926 func (w *PWriteReq) String() string { 927 return fmt.Sprintf("PWriteReq{Offset: %d, FD: %d, NumBytes: %d, Buf: [...%d bytes...]}", w.Offset, w.FD, w.NumBytes, len(w.Buf)) 928 } 929 930 // SizeBytes implements marshal.Marshallable.SizeBytes. 931 func (w *PWriteReq) SizeBytes() int { 932 return w.Offset.SizeBytes() + w.FD.SizeBytes() + w.NumBytes.SizeBytes() + int(w.NumBytes) 933 } 934 935 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 936 func (w *PWriteReq) MarshalBytes(dst []byte) []byte { 937 dst = w.Offset.MarshalUnsafe(dst) 938 dst = w.FD.MarshalUnsafe(dst) 939 dst = w.NumBytes.MarshalUnsafe(dst) 940 return dst[copy(dst[:w.NumBytes], w.Buf[:w.NumBytes]):] 941 } 942 943 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 944 func (w *PWriteReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 945 w.NumBytes = 0 946 if w.SizeBytes() > len(src) { 947 return src, false 948 } 949 srcRemain := w.Offset.UnmarshalUnsafe(src) 950 srcRemain = w.FD.UnmarshalUnsafe(srcRemain) 951 srcRemain = w.NumBytes.UnmarshalUnsafe(srcRemain) 952 953 // This is an optimization. Assuming that the server is making this call, it 954 // is safe to just point to src rather than allocating and copying. 955 if uint32(w.NumBytes) > uint32(len(srcRemain)) { 956 return src, false 957 } 958 w.Buf = srcRemain[:w.NumBytes] 959 return srcRemain[w.NumBytes:], true 960 } 961 962 // PWriteResp is used to return the result of pwrite(2). 963 // 964 // +marshal boundCheck 965 type PWriteResp struct { 966 Count uint64 967 } 968 969 // String implements fmt.Stringer.String. 970 func (w *PWriteResp) String() string { 971 return fmt.Sprintf("PWriteResp{Count: %d}", w.Count) 972 } 973 974 // MkdirAtReq is used to make MkdirAt requests. 975 type MkdirAtReq struct { 976 createCommon 977 Name SizedString 978 } 979 980 // String implements fmt.Stringer.String. 981 func (m *MkdirAtReq) String() string { 982 return fmt.Sprintf("MkdirAtReq{DirFD: %d, Mode: %s, UID: %d, GID: %d, Name: %s}", m.DirFD, m.Mode, m.UID, m.GID, m.Name) 983 } 984 985 // SizeBytes implements marshal.Marshallable.SizeBytes. 986 func (m *MkdirAtReq) SizeBytes() int { 987 return m.createCommon.SizeBytes() + m.Name.SizeBytes() 988 } 989 990 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 991 func (m *MkdirAtReq) MarshalBytes(dst []byte) []byte { 992 dst = m.createCommon.MarshalUnsafe(dst) 993 return m.Name.MarshalBytes(dst) 994 } 995 996 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 997 func (m *MkdirAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 998 m.Name = "" 999 if m.SizeBytes() > len(src) { 1000 return src, false 1001 } 1002 srcRemain := m.createCommon.UnmarshalUnsafe(src) 1003 if srcRemain, ok := m.Name.CheckedUnmarshal(srcRemain); ok { 1004 return srcRemain, true 1005 } 1006 return src, false 1007 } 1008 1009 // MkdirAtResp is the response to a successful MkdirAt request. 1010 // 1011 // +marshal boundCheck 1012 type MkdirAtResp struct { 1013 ChildDir Inode 1014 } 1015 1016 // String implements fmt.Stringer.String. 1017 func (m *MkdirAtResp) String() string { 1018 return fmt.Sprintf("MkdirAtResp{ChildDir: %s}", m.ChildDir.String()) 1019 } 1020 1021 // MknodAtReq is used to make MknodAt requests. 1022 type MknodAtReq struct { 1023 createCommon 1024 Minor primitive.Uint32 1025 Major primitive.Uint32 1026 Name SizedString 1027 } 1028 1029 // String implements fmt.Stringer.String. 1030 func (m *MknodAtReq) String() string { 1031 return fmt.Sprintf("MknodAtReq{DirFD: %d, Mode: %s, UID: %d, GID: %d, Minor: %d, Major: %d, Name: %s}", m.DirFD, m.Mode, m.UID, m.GID, m.Minor, m.Major, m.Name) 1032 } 1033 1034 // SizeBytes implements marshal.Marshallable.SizeBytes. 1035 func (m *MknodAtReq) SizeBytes() int { 1036 return m.createCommon.SizeBytes() + m.Minor.SizeBytes() + m.Major.SizeBytes() + m.Name.SizeBytes() 1037 } 1038 1039 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1040 func (m *MknodAtReq) MarshalBytes(dst []byte) []byte { 1041 dst = m.createCommon.MarshalUnsafe(dst) 1042 dst = m.Minor.MarshalUnsafe(dst) 1043 dst = m.Major.MarshalUnsafe(dst) 1044 return m.Name.MarshalBytes(dst) 1045 } 1046 1047 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1048 func (m *MknodAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1049 m.Name = "" 1050 if m.SizeBytes() > len(src) { 1051 return src, false 1052 } 1053 srcRemain := m.createCommon.UnmarshalUnsafe(src) 1054 srcRemain = m.Minor.UnmarshalUnsafe(srcRemain) 1055 srcRemain = m.Major.UnmarshalUnsafe(srcRemain) 1056 if srcRemain, ok := m.Name.CheckedUnmarshal(srcRemain); ok { 1057 return srcRemain, true 1058 } 1059 return src, false 1060 } 1061 1062 // MknodAtResp is the response to a successful MknodAt request. 1063 // 1064 // +marshal boundCheck 1065 type MknodAtResp struct { 1066 Child Inode 1067 } 1068 1069 // String implements fmt.Stringer.String. 1070 func (m *MknodAtResp) String() string { 1071 return fmt.Sprintf("MknodAtResp{Child: %s}", m.Child.String()) 1072 } 1073 1074 // SymlinkAtReq is used to make SymlinkAt request. 1075 type SymlinkAtReq struct { 1076 DirFD FDID 1077 UID UID 1078 GID GID 1079 Name SizedString 1080 Target SizedString 1081 } 1082 1083 // String implements fmt.Stringer.String. 1084 func (s *SymlinkAtReq) String() string { 1085 return fmt.Sprintf("SymlinkAtReq{DirFD: %d, UID: %d, GID: %d, Name: %s, Target: %s}", s.DirFD, s.UID, s.GID, s.Name, s.Target) 1086 } 1087 1088 // SizeBytes implements marshal.Marshallable.SizeBytes. 1089 func (s *SymlinkAtReq) SizeBytes() int { 1090 return s.DirFD.SizeBytes() + s.UID.SizeBytes() + s.GID.SizeBytes() + s.Name.SizeBytes() + s.Target.SizeBytes() 1091 } 1092 1093 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1094 func (s *SymlinkAtReq) MarshalBytes(dst []byte) []byte { 1095 dst = s.DirFD.MarshalUnsafe(dst) 1096 dst = s.UID.MarshalUnsafe(dst) 1097 dst = s.GID.MarshalUnsafe(dst) 1098 dst = s.Name.MarshalBytes(dst) 1099 return s.Target.MarshalBytes(dst) 1100 } 1101 1102 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1103 func (s *SymlinkAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1104 s.Name = "" 1105 s.Target = "" 1106 if s.SizeBytes() > len(src) { 1107 return src, false 1108 } 1109 srcRemain := s.DirFD.UnmarshalUnsafe(src) 1110 srcRemain = s.UID.UnmarshalUnsafe(srcRemain) 1111 srcRemain = s.GID.UnmarshalUnsafe(srcRemain) 1112 var ok bool 1113 if srcRemain, ok = s.Name.CheckedUnmarshal(srcRemain); !ok { 1114 return src, false 1115 } 1116 if srcRemain, ok = s.Target.CheckedUnmarshal(srcRemain); !ok { 1117 return src, false 1118 } 1119 return srcRemain, true 1120 } 1121 1122 // SymlinkAtResp is the response to a successful SymlinkAt request. 1123 // 1124 // +marshal boundCheck 1125 type SymlinkAtResp struct { 1126 Symlink Inode 1127 } 1128 1129 // String implements fmt.Stringer.String. 1130 func (s *SymlinkAtResp) String() string { 1131 return fmt.Sprintf("SymlinkAtResp{Symlink: %s}", s.Symlink.String()) 1132 } 1133 1134 // LinkAtReq is used to make LinkAt requests. 1135 type LinkAtReq struct { 1136 DirFD FDID 1137 Target FDID 1138 Name SizedString 1139 } 1140 1141 // String implements fmt.Stringer.String. 1142 func (l *LinkAtReq) String() string { 1143 return fmt.Sprintf("LinkAtReq{DirFD: %d, Target: %d, Name: %s}", l.DirFD, l.Target, l.Name) 1144 } 1145 1146 // SizeBytes implements marshal.Marshallable.SizeBytes. 1147 func (l *LinkAtReq) SizeBytes() int { 1148 return l.DirFD.SizeBytes() + l.Target.SizeBytes() + l.Name.SizeBytes() 1149 } 1150 1151 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1152 func (l *LinkAtReq) MarshalBytes(dst []byte) []byte { 1153 dst = l.DirFD.MarshalUnsafe(dst) 1154 dst = l.Target.MarshalUnsafe(dst) 1155 return l.Name.MarshalBytes(dst) 1156 } 1157 1158 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1159 func (l *LinkAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1160 l.Name = "" 1161 if l.SizeBytes() > len(src) { 1162 return src, false 1163 } 1164 srcRemain := l.DirFD.UnmarshalUnsafe(src) 1165 srcRemain = l.Target.UnmarshalUnsafe(srcRemain) 1166 if srcRemain, ok := l.Name.CheckedUnmarshal(srcRemain); ok { 1167 return srcRemain, true 1168 } 1169 return src, false 1170 } 1171 1172 // LinkAtResp is used to respond to a successful LinkAt request. 1173 // 1174 // +marshal boundCheck 1175 type LinkAtResp struct { 1176 Link Inode 1177 } 1178 1179 // String implements fmt.Stringer.String. 1180 func (l *LinkAtResp) String() string { 1181 return fmt.Sprintf("LinkAtResp{Link: %s}", l.Link.String()) 1182 } 1183 1184 // FStatFSReq is used to request StatFS results for the specified FD. 1185 // 1186 // +marshal boundCheck 1187 type FStatFSReq struct { 1188 FD FDID 1189 } 1190 1191 // String implements fmt.Stringer.String. 1192 func (s *FStatFSReq) String() string { 1193 return fmt.Sprintf("FStatFSReq{FD: %d}", s.FD) 1194 } 1195 1196 // StatFS is responded to a successful FStatFS request. 1197 // 1198 // +marshal boundCheck 1199 type StatFS struct { 1200 Type uint64 1201 BlockSize int64 1202 Blocks uint64 1203 BlocksFree uint64 1204 BlocksAvailable uint64 1205 Files uint64 1206 FilesFree uint64 1207 NameLength uint64 1208 } 1209 1210 // String implements fmt.Stringer.String. 1211 func (s *StatFS) String() string { 1212 return fmt.Sprintf("StatFS{Type: %d, BlockSize: %d, Blocks: %d, BlocksFree: %d, BlocksAvailable: %d, Files: %d, FilesFree: %d, NameLength: %d}", 1213 s.Type, s.BlockSize, s.Blocks, s.BlocksFree, s.BlocksAvailable, s.Files, s.FilesFree, s.NameLength) 1214 } 1215 1216 // FAllocateReq is used to request to fallocate(2) an FD. This has no response. 1217 // 1218 // +marshal boundCheck 1219 type FAllocateReq struct { 1220 FD FDID 1221 Mode uint64 1222 Offset uint64 1223 Length uint64 1224 } 1225 1226 // String implements fmt.Stringer.String. 1227 func (a *FAllocateReq) String() string { 1228 return fmt.Sprintf("FAllocateReq{FD: %d, Mode: %d, Offset: %d, Length: %d}", a.FD, a.Mode, a.Offset, a.Length) 1229 } 1230 1231 // FAllocateResp is an empty response to FAllocateReq. 1232 type FAllocateResp struct{ EmptyMessage } 1233 1234 // String implements fmt.Stringer.String. 1235 func (*FAllocateResp) String() string { 1236 return "FAllocateResp{}" 1237 } 1238 1239 // ReadLinkAtReq is used to readlinkat(2) at the specified FD. 1240 // 1241 // +marshal boundCheck 1242 type ReadLinkAtReq struct { 1243 FD FDID 1244 } 1245 1246 // String implements fmt.Stringer.String. 1247 func (r *ReadLinkAtReq) String() string { 1248 return fmt.Sprintf("ReadLinkAtReq{FD: %d}", r.FD) 1249 } 1250 1251 // ReadLinkAtResp is used to communicate ReadLinkAt results. 1252 type ReadLinkAtResp struct { 1253 Target SizedString 1254 } 1255 1256 // String implements fmt.Stringer.String. 1257 func (r *ReadLinkAtResp) String() string { 1258 return fmt.Sprintf("ReadLinkAtResp{Target: %s}", r.Target) 1259 } 1260 1261 // SizeBytes implements marshal.Marshallable.SizeBytes. 1262 func (r *ReadLinkAtResp) SizeBytes() int { 1263 return r.Target.SizeBytes() 1264 } 1265 1266 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1267 func (r *ReadLinkAtResp) MarshalBytes(dst []byte) []byte { 1268 return r.Target.MarshalBytes(dst) 1269 } 1270 1271 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1272 func (r *ReadLinkAtResp) CheckedUnmarshal(src []byte) ([]byte, bool) { 1273 return r.Target.CheckedUnmarshal(src) 1274 } 1275 1276 // FlushReq is used to make Flush requests. 1277 // 1278 // +marshal boundCheck 1279 type FlushReq struct { 1280 FD FDID 1281 } 1282 1283 // String implements fmt.Stringer.String. 1284 func (f *FlushReq) String() string { 1285 return fmt.Sprintf("FlushReq{FD: %d}", f.FD) 1286 } 1287 1288 // FlushResp is an empty response to FlushReq. 1289 type FlushResp struct{ EmptyMessage } 1290 1291 // String implements fmt.Stringer.String. 1292 func (*FlushResp) String() string { 1293 return "FlushResp{}" 1294 } 1295 1296 // ConnectReq is used to make a Connect request. 1297 // 1298 // +marshal boundCheck 1299 type ConnectReq struct { 1300 FD FDID 1301 // SockType is used to specify the socket type to connect to. As a special 1302 // case, SockType = 0 means that the socket type does not matter and the 1303 // requester will accept any socket type. 1304 SockType uint32 1305 _ uint32 // Need to make struct packed. 1306 } 1307 1308 // String implements fmt.Stringer.String. 1309 func (c *ConnectReq) String() string { 1310 return fmt.Sprintf("ConnectReq{FD: %d, SockType: %d}", c.FD, c.SockType) 1311 } 1312 1313 // ConnectResp is an empty response to ConnectReq. 1314 type ConnectResp struct{ EmptyMessage } 1315 1316 // String implements fmt.Stringer.String. 1317 func (*ConnectResp) String() string { 1318 return "ConnectResp{}" 1319 } 1320 1321 // BindAtReq is used to make BindAt requests. 1322 type BindAtReq struct { 1323 createCommon 1324 SockType primitive.Uint32 1325 Name SizedString 1326 } 1327 1328 // SizeBytes implements marshal.Marshallable.SizeBytes. 1329 func (b *BindAtReq) SizeBytes() int { 1330 return b.createCommon.SizeBytes() + b.SockType.SizeBytes() + b.Name.SizeBytes() 1331 } 1332 1333 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1334 func (b *BindAtReq) MarshalBytes(dst []byte) []byte { 1335 dst = b.createCommon.MarshalUnsafe(dst) 1336 dst = b.SockType.MarshalUnsafe(dst) 1337 return b.Name.MarshalBytes(dst) 1338 } 1339 1340 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1341 func (b *BindAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1342 b.Name = "" 1343 if b.SizeBytes() > len(src) { 1344 return src, false 1345 } 1346 srcRemain := b.createCommon.UnmarshalUnsafe(src) 1347 srcRemain = b.SockType.UnmarshalUnsafe(srcRemain) 1348 if srcRemain, ok := b.Name.CheckedUnmarshal(srcRemain); ok { 1349 return srcRemain, ok 1350 } 1351 return src, false 1352 } 1353 1354 // String implements fmt.Stringer.String. 1355 func (b *BindAtReq) String() string { 1356 return fmt.Sprintf("BindAtReq{DirFD: %d, Mode: %s, UID: %d, GID: %d, SockType: %d, Name: %q}", b.DirFD, b.Mode, b.UID, b.GID, b.SockType, b.Name) 1357 } 1358 1359 // BindAtResp is used to communicate BindAt response. 1360 // 1361 // +marshal boundCheck 1362 type BindAtResp struct { 1363 Child Inode 1364 BoundSocketFD FDID 1365 } 1366 1367 // String implements fmt.Stringer.String. 1368 func (b *BindAtResp) String() string { 1369 return fmt.Sprintf("BindAtResp{Child: %s, BoundSocketFD: %d}", b.Child.String(), b.BoundSocketFD) 1370 } 1371 1372 // ListenReq is used to make Listen requests. 1373 // 1374 // +marshal boundCheck 1375 type ListenReq struct { 1376 FD FDID 1377 Backlog int32 1378 _ uint32 1379 } 1380 1381 // String implements fmt.Stringer.String. 1382 func (l *ListenReq) String() string { 1383 return fmt.Sprintf("ListenReq{FD: %v, Backlog: %d}", l.FD, l.Backlog) 1384 } 1385 1386 // ListenResp is an empty response to ListenResp. 1387 type ListenResp struct{ EmptyMessage } 1388 1389 // String implements fmt.Stringer.String. 1390 func (*ListenResp) String() string { 1391 return "ListenResp{}" 1392 } 1393 1394 // AcceptReq is used to make AcceptRequests. 1395 // 1396 // +marshal boundCheck 1397 type AcceptReq struct { 1398 FD FDID 1399 } 1400 1401 // String implements fmt.Stringer.String. 1402 func (a *AcceptReq) String() string { 1403 return fmt.Sprintf("AcceptReq{FD: %v}", a.FD) 1404 } 1405 1406 // AcceptResp is an empty response to AcceptResp. 1407 type AcceptResp struct { 1408 PeerAddr SizedString 1409 } 1410 1411 // String implements fmt.Stringer.String. 1412 func (a *AcceptResp) String() string { 1413 return fmt.Sprintf("AcceptResp{PeerAddr: %s}", a.PeerAddr) 1414 } 1415 1416 // SizeBytes implements marshal.Marshallable.SizeBytes. 1417 func (a *AcceptResp) SizeBytes() int { 1418 return a.PeerAddr.SizeBytes() 1419 } 1420 1421 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1422 func (a *AcceptResp) MarshalBytes(dst []byte) []byte { 1423 return a.PeerAddr.MarshalBytes(dst) 1424 } 1425 1426 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1427 func (a *AcceptResp) CheckedUnmarshal(src []byte) ([]byte, bool) { 1428 return a.PeerAddr.CheckedUnmarshal(src) 1429 } 1430 1431 // UnlinkAtReq is used to make UnlinkAt request. 1432 type UnlinkAtReq struct { 1433 DirFD FDID 1434 Flags primitive.Uint32 1435 Name SizedString 1436 } 1437 1438 // String implements fmt.Stringer.String. 1439 func (u *UnlinkAtReq) String() string { 1440 return fmt.Sprintf("UnlinkAtReq{DirFD: %d, Flags: %#x, Name: %s}", u.DirFD, u.Flags, u.Name) 1441 } 1442 1443 // SizeBytes implements marshal.Marshallable.SizeBytes. 1444 func (u *UnlinkAtReq) SizeBytes() int { 1445 return u.DirFD.SizeBytes() + u.Flags.SizeBytes() + u.Name.SizeBytes() 1446 } 1447 1448 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1449 func (u *UnlinkAtReq) MarshalBytes(dst []byte) []byte { 1450 dst = u.DirFD.MarshalUnsafe(dst) 1451 dst = u.Flags.MarshalUnsafe(dst) 1452 return u.Name.MarshalBytes(dst) 1453 } 1454 1455 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1456 func (u *UnlinkAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1457 u.Name = "" 1458 if u.SizeBytes() > len(src) { 1459 return src, false 1460 } 1461 srcRemain := u.DirFD.UnmarshalUnsafe(src) 1462 srcRemain = u.Flags.UnmarshalUnsafe(srcRemain) 1463 if srcRemain, ok := u.Name.CheckedUnmarshal(srcRemain); ok { 1464 return srcRemain, true 1465 } 1466 return src, false 1467 } 1468 1469 // UnlinkAtResp is an empty response to UnlinkAtReq. 1470 type UnlinkAtResp struct{ EmptyMessage } 1471 1472 // String implements fmt.Stringer.String. 1473 func (*UnlinkAtResp) String() string { 1474 return "UnlinkAtResp{}" 1475 } 1476 1477 // RenameAtReq is used to make RenameAt requests. Note that the request takes in 1478 // the to-be-renamed file's FD instead of oldDir and oldName like renameat(2). 1479 type RenameAtReq struct { 1480 OldDir FDID 1481 NewDir FDID 1482 OldName SizedString 1483 NewName SizedString 1484 } 1485 1486 // String implements fmt.Stringer.String. 1487 func (r *RenameAtReq) String() string { 1488 return fmt.Sprintf("RenameAtReq{OldDir: %d, NewDir: %d, OldName: %s, NewName: %s}", r.OldDir, r.NewDir, r.OldName, r.NewName) 1489 } 1490 1491 // SizeBytes implements marshal.Marshallable.SizeBytes. 1492 func (r *RenameAtReq) SizeBytes() int { 1493 return r.OldDir.SizeBytes() + r.NewDir.SizeBytes() + r.OldName.SizeBytes() + r.NewName.SizeBytes() 1494 } 1495 1496 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1497 func (r *RenameAtReq) MarshalBytes(dst []byte) []byte { 1498 dst = r.OldDir.MarshalUnsafe(dst) 1499 dst = r.NewDir.MarshalUnsafe(dst) 1500 dst = r.OldName.MarshalBytes(dst) 1501 return r.NewName.MarshalBytes(dst) 1502 } 1503 1504 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1505 func (r *RenameAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1506 r.OldName = "" 1507 r.NewName = "" 1508 if r.SizeBytes() > len(src) { 1509 return src, false 1510 } 1511 srcRemain := r.OldDir.UnmarshalUnsafe(src) 1512 srcRemain = r.NewDir.UnmarshalUnsafe(srcRemain) 1513 var ok bool 1514 if srcRemain, ok = r.OldName.CheckedUnmarshal(srcRemain); !ok { 1515 return src, false 1516 } 1517 if srcRemain, ok = r.NewName.CheckedUnmarshal(srcRemain); !ok { 1518 return src, false 1519 } 1520 return srcRemain, true 1521 } 1522 1523 // RenameAtResp is an empty response to RenameAtReq. 1524 type RenameAtResp struct{ EmptyMessage } 1525 1526 // String implements fmt.Stringer.String. 1527 func (*RenameAtResp) String() string { 1528 return "RenameAtResp{}" 1529 } 1530 1531 // Getdents64Req is used to make Getdents64 requests. 1532 // 1533 // +marshal boundCheck 1534 type Getdents64Req struct { 1535 DirFD FDID 1536 // Count is the number of bytes to read. A negative value of Count is used to 1537 // indicate that the implementation must lseek(0, SEEK_SET) before calling 1538 // getdents64(2). Implementations must use the absolute value of Count to 1539 // determine the number of bytes to read. 1540 Count int32 1541 _ uint32 // Need to make struct packed. 1542 } 1543 1544 // String implements fmt.Stringer.String. 1545 func (g *Getdents64Req) String() string { 1546 return fmt.Sprintf("Getdents64Req{DirFD: %d, Count: %d}", g.DirFD, g.Count) 1547 } 1548 1549 // Dirent64 is analogous to struct linux_dirent64. 1550 type Dirent64 struct { 1551 Ino primitive.Uint64 1552 DevMinor primitive.Uint32 1553 DevMajor primitive.Uint32 1554 Off primitive.Uint64 1555 Type primitive.Uint8 1556 Name SizedString 1557 } 1558 1559 // String implements fmt.Stringer.String. 1560 func (d *Dirent64) String() string { 1561 return fmt.Sprintf("Dirent64{Ino: %d, DevMinor: %d, DevMajor: %d, Off: %d, Type: %d, Name: %s}", d.Ino, d.DevMinor, d.DevMajor, d.Off, d.Type, d.Name) 1562 } 1563 1564 // SizeBytes implements marshal.Marshallable.SizeBytes. 1565 func (d *Dirent64) SizeBytes() int { 1566 return d.Ino.SizeBytes() + d.DevMinor.SizeBytes() + d.DevMajor.SizeBytes() + d.Off.SizeBytes() + d.Type.SizeBytes() + d.Name.SizeBytes() 1567 } 1568 1569 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1570 func (d *Dirent64) MarshalBytes(dst []byte) []byte { 1571 dst = d.Ino.MarshalUnsafe(dst) 1572 dst = d.DevMinor.MarshalUnsafe(dst) 1573 dst = d.DevMajor.MarshalUnsafe(dst) 1574 dst = d.Off.MarshalUnsafe(dst) 1575 dst = d.Type.MarshalUnsafe(dst) 1576 return d.Name.MarshalBytes(dst) 1577 } 1578 1579 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1580 func (d *Dirent64) CheckedUnmarshal(src []byte) ([]byte, bool) { 1581 d.Name = "" 1582 if d.SizeBytes() > len(src) { 1583 return src, false 1584 } 1585 srcRemain := d.Ino.UnmarshalUnsafe(src) 1586 srcRemain = d.DevMinor.UnmarshalUnsafe(srcRemain) 1587 srcRemain = d.DevMajor.UnmarshalUnsafe(srcRemain) 1588 srcRemain = d.Off.UnmarshalUnsafe(srcRemain) 1589 srcRemain = d.Type.UnmarshalUnsafe(srcRemain) 1590 if srcRemain, ok := d.Name.CheckedUnmarshal(srcRemain); ok { 1591 return srcRemain, true 1592 } 1593 return src, false 1594 } 1595 1596 // Getdents64Resp is used to communicate getdents64 results. In memory, the 1597 // dirents array is preceded by a uint16 integer denoting array length. 1598 type Getdents64Resp struct { 1599 Dirents []Dirent64 1600 } 1601 1602 // String implements fmt.Stringer.String. 1603 func (g *Getdents64Resp) String() string { 1604 var b strings.Builder 1605 b.WriteString("[") 1606 for i, dirent := range g.Dirents { 1607 if i > 0 { 1608 b.WriteString(", ") 1609 } 1610 b.WriteString(dirent.String()) 1611 } 1612 b.WriteString("]") 1613 return fmt.Sprintf("Getdents64Resp{Dirents: %s}", b.String()) 1614 } 1615 1616 // SizeBytes implements marshal.Marshallable.SizeBytes. 1617 func (g *Getdents64Resp) SizeBytes() int { 1618 ret := (*primitive.Uint16)(nil).SizeBytes() 1619 for i := range g.Dirents { 1620 ret += g.Dirents[i].SizeBytes() 1621 } 1622 return ret 1623 } 1624 1625 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1626 func (g *Getdents64Resp) MarshalBytes(dst []byte) []byte { 1627 numDirents := primitive.Uint16(len(g.Dirents)) 1628 dst = numDirents.MarshalUnsafe(dst) 1629 for i := range g.Dirents { 1630 dst = g.Dirents[i].MarshalBytes(dst) 1631 } 1632 return dst 1633 } 1634 1635 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1636 func (g *Getdents64Resp) CheckedUnmarshal(src []byte) ([]byte, bool) { 1637 g.Dirents = g.Dirents[:0] 1638 if g.SizeBytes() > len(src) { 1639 return src, false 1640 } 1641 var numDirents primitive.Uint16 1642 srcRemain := numDirents.UnmarshalUnsafe(src) 1643 if cap(g.Dirents) < int(numDirents) { 1644 g.Dirents = make([]Dirent64, numDirents) 1645 } else { 1646 g.Dirents = g.Dirents[:numDirents] 1647 } 1648 1649 var ok bool 1650 for i := range g.Dirents { 1651 if srcRemain, ok = g.Dirents[i].CheckedUnmarshal(srcRemain); !ok { 1652 return src, false 1653 } 1654 } 1655 return srcRemain, true 1656 } 1657 1658 // FGetXattrReq is used to make FGetXattr requests. The response to this is 1659 // just a SizedString containing the xattr value. 1660 type FGetXattrReq struct { 1661 FD FDID 1662 BufSize primitive.Uint32 1663 Name SizedString 1664 } 1665 1666 // String implements fmt.Stringer.String. 1667 func (g *FGetXattrReq) String() string { 1668 return fmt.Sprintf("FGetXattrReq{FD: %d, BufSize: %d, Name: %s}", g.FD, g.BufSize, g.Name) 1669 } 1670 1671 // SizeBytes implements marshal.Marshallable.SizeBytes. 1672 func (g *FGetXattrReq) SizeBytes() int { 1673 return g.FD.SizeBytes() + g.BufSize.SizeBytes() + g.Name.SizeBytes() 1674 } 1675 1676 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1677 func (g *FGetXattrReq) MarshalBytes(dst []byte) []byte { 1678 dst = g.FD.MarshalUnsafe(dst) 1679 dst = g.BufSize.MarshalUnsafe(dst) 1680 return g.Name.MarshalBytes(dst) 1681 } 1682 1683 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1684 func (g *FGetXattrReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1685 g.Name = "" 1686 if g.SizeBytes() > len(src) { 1687 return src, false 1688 } 1689 srcRemain := g.FD.UnmarshalUnsafe(src) 1690 srcRemain = g.BufSize.UnmarshalUnsafe(srcRemain) 1691 if srcRemain, ok := g.Name.CheckedUnmarshal(srcRemain); ok { 1692 return srcRemain, true 1693 } 1694 return src, false 1695 } 1696 1697 // FGetXattrResp is used to respond to FGetXattr request. 1698 type FGetXattrResp struct { 1699 Value SizedString 1700 } 1701 1702 // String implements fmt.Stringer.String. 1703 func (g *FGetXattrResp) String() string { 1704 return fmt.Sprintf("FGetXattrResp{Value: %s}", g.Value) 1705 } 1706 1707 // SizeBytes implements marshal.Marshallable.SizeBytes. 1708 func (g *FGetXattrResp) SizeBytes() int { 1709 return g.Value.SizeBytes() 1710 } 1711 1712 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1713 func (g *FGetXattrResp) MarshalBytes(dst []byte) []byte { 1714 return g.Value.MarshalBytes(dst) 1715 } 1716 1717 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1718 func (g *FGetXattrResp) CheckedUnmarshal(src []byte) ([]byte, bool) { 1719 return g.Value.CheckedUnmarshal(src) 1720 } 1721 1722 // FSetXattrReq is used to make FSetXattr requests. It has no response. 1723 type FSetXattrReq struct { 1724 FD FDID 1725 Flags primitive.Uint32 1726 Name SizedString 1727 Value SizedString 1728 } 1729 1730 // String implements fmt.Stringer.String. 1731 func (s *FSetXattrReq) String() string { 1732 return fmt.Sprintf("FSetXattrReq{FD: %d, Flags: %#x, Name: %s, Value: %s}", s.FD, s.Flags, s.Name, s.Value) 1733 } 1734 1735 // SizeBytes implements marshal.Marshallable.SizeBytes. 1736 func (s *FSetXattrReq) SizeBytes() int { 1737 return s.FD.SizeBytes() + s.Flags.SizeBytes() + s.Name.SizeBytes() + s.Value.SizeBytes() 1738 } 1739 1740 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1741 func (s *FSetXattrReq) MarshalBytes(dst []byte) []byte { 1742 dst = s.FD.MarshalUnsafe(dst) 1743 dst = s.Flags.MarshalUnsafe(dst) 1744 dst = s.Name.MarshalBytes(dst) 1745 return s.Value.MarshalBytes(dst) 1746 } 1747 1748 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1749 func (s *FSetXattrReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1750 s.Name = "" 1751 s.Value = "" 1752 if s.SizeBytes() > len(src) { 1753 return src, false 1754 } 1755 srcRemain := s.FD.UnmarshalUnsafe(src) 1756 srcRemain = s.Flags.UnmarshalUnsafe(srcRemain) 1757 var ok bool 1758 if srcRemain, ok = s.Name.CheckedUnmarshal(srcRemain); !ok { 1759 return src, false 1760 } 1761 if srcRemain, ok = s.Value.CheckedUnmarshal(srcRemain); !ok { 1762 return src, false 1763 } 1764 return srcRemain, true 1765 } 1766 1767 // FSetXattrResp is an empty response to FSetXattrReq. 1768 type FSetXattrResp struct{ EmptyMessage } 1769 1770 // String implements fmt.Stringer.String. 1771 func (*FSetXattrResp) String() string { 1772 return "FSetXattrResp{}" 1773 } 1774 1775 // FRemoveXattrReq is used to make FRemoveXattr requests. It has no response. 1776 type FRemoveXattrReq struct { 1777 FD FDID 1778 Name SizedString 1779 } 1780 1781 // String implements fmt.Stringer.String. 1782 func (r *FRemoveXattrReq) String() string { 1783 return fmt.Sprintf("FRemoveXattrReq{FD: %d, Name: %s}", r.FD, r.Name) 1784 } 1785 1786 // SizeBytes implements marshal.Marshallable.SizeBytes. 1787 func (r *FRemoveXattrReq) SizeBytes() int { 1788 return r.FD.SizeBytes() + r.Name.SizeBytes() 1789 } 1790 1791 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1792 func (r *FRemoveXattrReq) MarshalBytes(dst []byte) []byte { 1793 dst = r.FD.MarshalUnsafe(dst) 1794 return r.Name.MarshalBytes(dst) 1795 } 1796 1797 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1798 func (r *FRemoveXattrReq) CheckedUnmarshal(src []byte) ([]byte, bool) { 1799 r.Name = "" 1800 if r.SizeBytes() > len(src) { 1801 return src, false 1802 } 1803 srcRemain := r.FD.UnmarshalUnsafe(src) 1804 if srcRemain, ok := r.Name.CheckedUnmarshal(srcRemain); ok { 1805 return srcRemain, true 1806 } 1807 return src, false 1808 } 1809 1810 // FRemoveXattrResp is an empty response to FRemoveXattrReq. 1811 type FRemoveXattrResp struct{ EmptyMessage } 1812 1813 // String implements fmt.Stringer.String. 1814 func (*FRemoveXattrResp) String() string { 1815 return "FRemoveXattrResp{}" 1816 } 1817 1818 // FListXattrReq is used to make FListXattr requests. 1819 // 1820 // +marshal boundCheck 1821 type FListXattrReq struct { 1822 FD FDID 1823 Size uint64 1824 } 1825 1826 // String implements fmt.Stringer.String. 1827 func (l *FListXattrReq) String() string { 1828 return fmt.Sprintf("FListXattrReq{FD: %d, Size: %d}", l.FD, l.Size) 1829 } 1830 1831 // FListXattrResp is used to respond to FListXattr requests. 1832 type FListXattrResp struct { 1833 Xattrs StringArray 1834 } 1835 1836 // String implements fmt.Stringer.String. 1837 func (l *FListXattrResp) String() string { 1838 return fmt.Sprintf("FListXattrResp{Xattrs: %s}", l.Xattrs.String()) 1839 } 1840 1841 // SizeBytes implements marshal.Marshallable.SizeBytes. 1842 func (l *FListXattrResp) SizeBytes() int { 1843 return l.Xattrs.SizeBytes() 1844 } 1845 1846 // MarshalBytes implements marshal.Marshallable.MarshalBytes. 1847 func (l *FListXattrResp) MarshalBytes(dst []byte) []byte { 1848 return l.Xattrs.MarshalBytes(dst) 1849 } 1850 1851 // CheckedUnmarshal implements marshal.CheckedMarshallable.CheckedUnmarshal. 1852 func (l *FListXattrResp) CheckedUnmarshal(src []byte) ([]byte, bool) { 1853 return l.Xattrs.CheckedUnmarshal(src) 1854 }