github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/p9/p9.go (about) 1 // Copyright 2018 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 p9 is a 9P2000.L implementation. 16 package p9 17 18 import ( 19 "fmt" 20 "math" 21 "os" 22 "strings" 23 "sync/atomic" 24 "syscall" 25 26 "golang.org/x/sys/unix" 27 ) 28 29 // OpenFlags is the mode passed to Open and Create operations. 30 // 31 // These correspond to bits sent over the wire. 32 type OpenFlags uint32 33 34 const ( 35 // ReadOnly is a Tlopen and Tlcreate flag indicating read-only mode. 36 ReadOnly OpenFlags = 0 37 38 // WriteOnly is a Tlopen and Tlcreate flag indicating write-only mode. 39 WriteOnly OpenFlags = 1 40 41 // ReadWrite is a Tlopen flag indicates read-write mode. 42 ReadWrite OpenFlags = 2 43 44 // OpenFlagsModeMask is a mask of valid OpenFlags mode bits. 45 OpenFlagsModeMask OpenFlags = 3 46 47 // OpenTruncate is a Tlopen flag indicating that the opened file should be 48 // truncated. 49 OpenTruncate OpenFlags = 01000 50 ) 51 52 // ConnectFlags is the mode passed to Connect operations. 53 // 54 // These correspond to bits sent over the wire. 55 type ConnectFlags uint32 56 57 const ( 58 // StreamSocket is a Tlconnect flag indicating SOCK_STREAM mode. 59 StreamSocket ConnectFlags = 0 60 61 // DgramSocket is a Tlconnect flag indicating SOCK_DGRAM mode. 62 DgramSocket ConnectFlags = 1 63 64 // SeqpacketSocket is a Tlconnect flag indicating SOCK_SEQPACKET mode. 65 SeqpacketSocket ConnectFlags = 2 66 67 // AnonymousSocket is a Tlconnect flag indicating that the mode does not 68 // matter and that the requester will accept any socket type. 69 AnonymousSocket ConnectFlags = 3 70 ) 71 72 // OSFlags converts a p9.OpenFlags to an int compatible with open(2). 73 func (o OpenFlags) OSFlags() int { 74 // "flags contains Linux open(2) flags bits" - 9P2000.L 75 return int(o) 76 } 77 78 // String implements fmt.Stringer. 79 func (o OpenFlags) String() string { 80 var buf strings.Builder 81 switch mode := o & OpenFlagsModeMask; mode { 82 case ReadOnly: 83 buf.WriteString("ReadOnly") 84 case WriteOnly: 85 buf.WriteString("WriteOnly") 86 case ReadWrite: 87 buf.WriteString("ReadWrite") 88 default: 89 fmt.Fprintf(&buf, "%#o", mode) 90 } 91 otherFlags := o &^ OpenFlagsModeMask 92 if otherFlags&OpenTruncate != 0 { 93 buf.WriteString("|OpenTruncate") 94 otherFlags &^= OpenTruncate 95 } 96 if otherFlags != 0 { 97 fmt.Fprintf(&buf, "|%#o", otherFlags) 98 } 99 return buf.String() 100 } 101 102 // Tag is a message tag. 103 type Tag uint16 104 105 // FID is a file identifier. 106 type FID uint64 107 108 // FileMode are flags corresponding to file modes. 109 // 110 // These correspond to bits sent over the wire. 111 // These also correspond to mode_t bits. 112 type FileMode uint32 113 114 const ( 115 // FileModeMask is a mask of all the file mode bits of FileMode. 116 FileModeMask FileMode = 0170000 117 118 // ModeSocket is an (unused) mode bit for a socket. 119 ModeSocket FileMode = 0140000 120 121 // ModeSymlink is a mode bit for a symlink. 122 ModeSymlink FileMode = 0120000 123 124 // ModeRegular is a mode bit for regular files. 125 ModeRegular FileMode = 0100000 126 127 // ModeBlockDevice is a mode bit for block devices. 128 ModeBlockDevice FileMode = 060000 129 130 // ModeDirectory is a mode bit for directories. 131 ModeDirectory FileMode = 040000 132 133 // ModeCharacterDevice is a mode bit for a character device. 134 ModeCharacterDevice FileMode = 020000 135 136 // ModeNamedPipe is a mode bit for a named pipe. 137 ModeNamedPipe FileMode = 010000 138 139 // Read is a mode bit indicating read permission. 140 Read FileMode = 04 141 142 // Write is a mode bit indicating write permission. 143 Write FileMode = 02 144 145 // Exec is a mode bit indicating exec permission. 146 Exec FileMode = 01 147 148 // AllPermissions is a mask with rwx bits set for user, group and others. 149 AllPermissions FileMode = 0777 150 151 // Sticky is a mode bit indicating sticky directories. 152 Sticky FileMode = 01000 153 154 // SetGID is the set group ID bit. 155 SetGID FileMode = 02000 156 157 // SetUID is the set user ID bit. 158 SetUID FileMode = 04000 159 160 // permissionsMask is the mask to apply to FileModes for permissions. It 161 // includes rwx bits for user, group, and others, as well as the sticky 162 // bit, setuid bit, and setgid bit. 163 permissionsMask FileMode = 07777 164 ) 165 166 // QIDType is the most significant byte of the FileMode word, to be used as the 167 // Type field of p9.QID. 168 func (m FileMode) QIDType() QIDType { 169 switch { 170 case m.IsDir(): 171 return TypeDir 172 case m.IsSocket(), m.IsNamedPipe(), m.IsCharacterDevice(): 173 // Best approximation. 174 return TypeAppendOnly 175 case m.IsSymlink(): 176 return TypeSymlink 177 default: 178 return TypeRegular 179 } 180 } 181 182 // FileType returns the file mode without the permission bits. 183 func (m FileMode) FileType() FileMode { 184 return m & FileModeMask 185 } 186 187 // Permissions returns just the permission bits of the mode. 188 func (m FileMode) Permissions() FileMode { 189 return m & permissionsMask 190 } 191 192 // Writable returns the mode with write bits added. 193 func (m FileMode) Writable() FileMode { 194 return m | 0222 195 } 196 197 // IsReadable returns true if m represents a file that can be read. 198 func (m FileMode) IsReadable() bool { 199 return m&0444 != 0 200 } 201 202 // IsWritable returns true if m represents a file that can be written to. 203 func (m FileMode) IsWritable() bool { 204 return m&0222 != 0 205 } 206 207 // IsExecutable returns true if m represents a file that can be executed. 208 func (m FileMode) IsExecutable() bool { 209 return m&0111 != 0 210 } 211 212 // IsRegular returns true if m is a regular file. 213 func (m FileMode) IsRegular() bool { 214 return m&FileModeMask == ModeRegular 215 } 216 217 // IsDir returns true if m represents a directory. 218 func (m FileMode) IsDir() bool { 219 return m&FileModeMask == ModeDirectory 220 } 221 222 // IsNamedPipe returns true if m represents a named pipe. 223 func (m FileMode) IsNamedPipe() bool { 224 return m&FileModeMask == ModeNamedPipe 225 } 226 227 // IsCharacterDevice returns true if m represents a character device. 228 func (m FileMode) IsCharacterDevice() bool { 229 return m&FileModeMask == ModeCharacterDevice 230 } 231 232 // IsBlockDevice returns true if m represents a character device. 233 func (m FileMode) IsBlockDevice() bool { 234 return m&FileModeMask == ModeBlockDevice 235 } 236 237 // IsSocket returns true if m represents a socket. 238 func (m FileMode) IsSocket() bool { 239 return m&FileModeMask == ModeSocket 240 } 241 242 // IsSymlink returns true if m represents a symlink. 243 func (m FileMode) IsSymlink() bool { 244 return m&FileModeMask == ModeSymlink 245 } 246 247 // ModeFromOS returns a FileMode from an os.FileMode. 248 func ModeFromOS(mode os.FileMode) FileMode { 249 m := FileMode(mode.Perm()) 250 switch { 251 case mode.IsDir(): 252 m |= ModeDirectory 253 case mode&os.ModeSymlink != 0: 254 m |= ModeSymlink 255 case mode&os.ModeSocket != 0: 256 m |= ModeSocket 257 case mode&os.ModeNamedPipe != 0: 258 m |= ModeNamedPipe 259 case mode&os.ModeCharDevice != 0: 260 m |= ModeCharacterDevice 261 case mode&os.ModeDevice != 0: 262 m |= ModeBlockDevice 263 default: 264 m |= ModeRegular 265 } 266 return m 267 } 268 269 // OSMode converts a p9.FileMode to an os.FileMode. 270 func (m FileMode) OSMode() os.FileMode { 271 var osMode os.FileMode 272 osMode |= os.FileMode(m.Permissions()) 273 switch { 274 case m.IsDir(): 275 osMode |= os.ModeDir 276 case m.IsSymlink(): 277 osMode |= os.ModeSymlink 278 case m.IsSocket(): 279 osMode |= os.ModeSocket 280 case m.IsNamedPipe(): 281 osMode |= os.ModeNamedPipe 282 case m.IsCharacterDevice(): 283 osMode |= os.ModeCharDevice | os.ModeDevice 284 case m.IsBlockDevice(): 285 osMode |= os.ModeDevice 286 } 287 return osMode 288 } 289 290 // UID represents a user ID. 291 type UID uint32 292 293 // Ok returns true if uid is not NoUID. 294 func (uid UID) Ok() bool { 295 return uid != NoUID 296 } 297 298 // GID represents a group ID. 299 type GID uint32 300 301 // Ok returns true if gid is not NoGID. 302 func (gid GID) Ok() bool { 303 return gid != NoGID 304 } 305 306 const ( 307 // NoTag is a sentinel used to indicate no valid tag. 308 NoTag Tag = math.MaxUint16 309 310 // NoFID is a sentinel used to indicate no valid FID. 311 NoFID FID = math.MaxUint32 312 313 // NoUID is a sentinel used to indicate no valid UID. 314 NoUID UID = math.MaxUint32 315 316 // NoGID is a sentinel used to indicate no valid GID. 317 NoGID GID = math.MaxUint32 318 ) 319 320 // MsgType is a type identifier. 321 type MsgType uint8 322 323 // MsgType declarations. 324 const ( 325 MsgTlerror MsgType = 6 326 MsgRlerror MsgType = 7 327 MsgTstatfs MsgType = 8 328 MsgRstatfs MsgType = 9 329 MsgTlopen MsgType = 12 330 MsgRlopen MsgType = 13 331 MsgTlcreate MsgType = 14 332 MsgRlcreate MsgType = 15 333 MsgTsymlink MsgType = 16 334 MsgRsymlink MsgType = 17 335 MsgTmknod MsgType = 18 336 MsgRmknod MsgType = 19 337 MsgTrename MsgType = 20 338 MsgRrename MsgType = 21 339 MsgTreadlink MsgType = 22 340 MsgRreadlink MsgType = 23 341 MsgTgetattr MsgType = 24 342 MsgRgetattr MsgType = 25 343 MsgTsetattr MsgType = 26 344 MsgRsetattr MsgType = 27 345 MsgTlistxattr MsgType = 28 346 MsgRlistxattr MsgType = 29 347 MsgTxattrwalk MsgType = 30 348 MsgRxattrwalk MsgType = 31 349 MsgTxattrcreate MsgType = 32 350 MsgRxattrcreate MsgType = 33 351 MsgTgetxattr MsgType = 34 352 MsgRgetxattr MsgType = 35 353 MsgTsetxattr MsgType = 36 354 MsgRsetxattr MsgType = 37 355 MsgTremovexattr MsgType = 38 356 MsgRremovexattr MsgType = 39 357 MsgTreaddir MsgType = 40 358 MsgRreaddir MsgType = 41 359 MsgTfsync MsgType = 50 360 MsgRfsync MsgType = 51 361 MsgTlink MsgType = 70 362 MsgRlink MsgType = 71 363 MsgTmkdir MsgType = 72 364 MsgRmkdir MsgType = 73 365 MsgTrenameat MsgType = 74 366 MsgRrenameat MsgType = 75 367 MsgTunlinkat MsgType = 76 368 MsgRunlinkat MsgType = 77 369 MsgTversion MsgType = 100 370 MsgRversion MsgType = 101 371 MsgTauth MsgType = 102 372 MsgRauth MsgType = 103 373 MsgTattach MsgType = 104 374 MsgRattach MsgType = 105 375 MsgTflush MsgType = 108 376 MsgRflush MsgType = 109 377 MsgTwalk MsgType = 110 378 MsgRwalk MsgType = 111 379 MsgTread MsgType = 116 380 MsgRread MsgType = 117 381 MsgTwrite MsgType = 118 382 MsgRwrite MsgType = 119 383 MsgTclunk MsgType = 120 384 MsgRclunk MsgType = 121 385 MsgTremove MsgType = 122 386 MsgRremove MsgType = 123 387 MsgTflushf MsgType = 124 388 MsgRflushf MsgType = 125 389 MsgTwalkgetattr MsgType = 126 390 MsgRwalkgetattr MsgType = 127 391 MsgTucreate MsgType = 128 392 MsgRucreate MsgType = 129 393 MsgTumkdir MsgType = 130 394 MsgRumkdir MsgType = 131 395 MsgTumknod MsgType = 132 396 MsgRumknod MsgType = 133 397 MsgTusymlink MsgType = 134 398 MsgRusymlink MsgType = 135 399 MsgTlconnect MsgType = 136 400 MsgRlconnect MsgType = 137 401 MsgTallocate MsgType = 138 402 MsgRallocate MsgType = 139 403 MsgTsetattrclunk MsgType = 140 404 MsgRsetattrclunk MsgType = 141 405 MsgTmultigetattr MsgType = 142 406 MsgRmultigetattr MsgType = 143 407 MsgTchannel MsgType = 250 408 MsgRchannel MsgType = 251 409 ) 410 411 // QIDType represents the file type for QIDs. 412 // 413 // QIDType corresponds to the high 8 bits of a Plan 9 file mode. 414 type QIDType uint8 415 416 const ( 417 // TypeDir represents a directory type. 418 TypeDir QIDType = 0x80 419 420 // TypeAppendOnly represents an append only file. 421 TypeAppendOnly QIDType = 0x40 422 423 // TypeExclusive represents an exclusive-use file. 424 TypeExclusive QIDType = 0x20 425 426 // TypeMount represents a mounted channel. 427 TypeMount QIDType = 0x10 428 429 // TypeAuth represents an authentication file. 430 TypeAuth QIDType = 0x08 431 432 // TypeTemporary represents a temporary file. 433 TypeTemporary QIDType = 0x04 434 435 // TypeSymlink represents a symlink. 436 TypeSymlink QIDType = 0x02 437 438 // TypeLink represents a hard link. 439 TypeLink QIDType = 0x01 440 441 // TypeRegular represents a regular file. 442 TypeRegular QIDType = 0x00 443 ) 444 445 // QID is a unique file identifier. 446 // 447 // This may be embedded in other requests and responses. 448 type QID struct { 449 // Type is the highest order byte of the file mode. 450 Type QIDType 451 452 // Version is an arbitrary server version number. 453 Version uint32 454 455 // Path is a unique server identifier for this path (e.g. inode). 456 Path uint64 457 } 458 459 // String implements fmt.Stringer. 460 func (q QID) String() string { 461 return fmt.Sprintf("QID{Type: %d, Version: %d, Path: %d}", q.Type, q.Version, q.Path) 462 } 463 464 // decode implements encoder.decode. 465 func (q *QID) decode(b *buffer) { 466 q.Type = b.ReadQIDType() 467 q.Version = b.Read32() 468 q.Path = b.Read64() 469 } 470 471 // encode implements encoder.encode. 472 func (q *QID) encode(b *buffer) { 473 b.WriteQIDType(q.Type) 474 b.Write32(q.Version) 475 b.Write64(q.Path) 476 } 477 478 // QIDGenerator is a simple generator for QIDs that atomically increments Path 479 // values. 480 type QIDGenerator struct { 481 // uids is an ever increasing value that can be atomically incremented 482 // to provide unique Path values for QIDs. 483 uids uint64 484 } 485 486 // Get returns a new 9P unique ID with a unique Path given a QID type. 487 // 488 // While the 9P spec allows Version to be incremented every time the file is 489 // modified, we currently do not use the Version member for anything. Hence, 490 // it is set to 0. 491 func (q *QIDGenerator) Get(t QIDType) QID { 492 return QID{ 493 Type: t, 494 Version: 0, 495 Path: atomic.AddUint64(&q.uids, 1), 496 } 497 } 498 499 // FSStat is used by statfs. 500 type FSStat struct { 501 // Type is the filesystem type. 502 Type uint32 503 504 // BlockSize is the blocksize. 505 BlockSize uint32 506 507 // Blocks is the number of blocks. 508 Blocks uint64 509 510 // BlocksFree is the number of free blocks. 511 BlocksFree uint64 512 513 // BlocksAvailable is the number of blocks *available*. 514 BlocksAvailable uint64 515 516 // Files is the number of files available. 517 Files uint64 518 519 // FilesFree is the number of free file nodes. 520 FilesFree uint64 521 522 // FSID is the filesystem ID. 523 FSID uint64 524 525 // NameLength is the maximum name length. 526 NameLength uint32 527 } 528 529 // decode implements encoder.decode. 530 func (f *FSStat) decode(b *buffer) { 531 f.Type = b.Read32() 532 f.BlockSize = b.Read32() 533 f.Blocks = b.Read64() 534 f.BlocksFree = b.Read64() 535 f.BlocksAvailable = b.Read64() 536 f.Files = b.Read64() 537 f.FilesFree = b.Read64() 538 f.FSID = b.Read64() 539 f.NameLength = b.Read32() 540 } 541 542 // encode implements encoder.encode. 543 func (f *FSStat) encode(b *buffer) { 544 b.Write32(f.Type) 545 b.Write32(f.BlockSize) 546 b.Write64(f.Blocks) 547 b.Write64(f.BlocksFree) 548 b.Write64(f.BlocksAvailable) 549 b.Write64(f.Files) 550 b.Write64(f.FilesFree) 551 b.Write64(f.FSID) 552 b.Write32(f.NameLength) 553 } 554 555 // AttrMask is a mask of attributes for getattr. 556 type AttrMask struct { 557 Mode bool 558 NLink bool 559 UID bool 560 GID bool 561 RDev bool 562 ATime bool 563 MTime bool 564 CTime bool 565 INo bool 566 Size bool 567 Blocks bool 568 BTime bool 569 Gen bool 570 DataVersion bool 571 } 572 573 // Contains returns true if a contains all of the attributes masked as b. 574 func (a AttrMask) Contains(b AttrMask) bool { 575 if b.Mode && !a.Mode { 576 return false 577 } 578 if b.NLink && !a.NLink { 579 return false 580 } 581 if b.UID && !a.UID { 582 return false 583 } 584 if b.GID && !a.GID { 585 return false 586 } 587 if b.RDev && !a.RDev { 588 return false 589 } 590 if b.ATime && !a.ATime { 591 return false 592 } 593 if b.MTime && !a.MTime { 594 return false 595 } 596 if b.CTime && !a.CTime { 597 return false 598 } 599 if b.INo && !a.INo { 600 return false 601 } 602 if b.Size && !a.Size { 603 return false 604 } 605 if b.Blocks && !a.Blocks { 606 return false 607 } 608 if b.BTime && !a.BTime { 609 return false 610 } 611 if b.Gen && !a.Gen { 612 return false 613 } 614 if b.DataVersion && !a.DataVersion { 615 return false 616 } 617 return true 618 } 619 620 // Empty returns true if no fields are masked. 621 func (a AttrMask) Empty() bool { 622 return !a.Mode && !a.NLink && !a.UID && !a.GID && !a.RDev && !a.ATime && !a.MTime && !a.CTime && !a.INo && !a.Size && !a.Blocks && !a.BTime && !a.Gen && !a.DataVersion 623 } 624 625 // AttrMaskAll returns an AttrMask with all fields masked. 626 func AttrMaskAll() AttrMask { 627 return AttrMask{ 628 Mode: true, 629 NLink: true, 630 UID: true, 631 GID: true, 632 RDev: true, 633 ATime: true, 634 MTime: true, 635 CTime: true, 636 INo: true, 637 Size: true, 638 Blocks: true, 639 BTime: true, 640 Gen: true, 641 DataVersion: true, 642 } 643 } 644 645 // String implements fmt.Stringer. 646 func (a AttrMask) String() string { 647 var masks []string 648 if a.Mode { 649 masks = append(masks, "Mode") 650 } 651 if a.NLink { 652 masks = append(masks, "NLink") 653 } 654 if a.UID { 655 masks = append(masks, "UID") 656 } 657 if a.GID { 658 masks = append(masks, "GID") 659 } 660 if a.RDev { 661 masks = append(masks, "RDev") 662 } 663 if a.ATime { 664 masks = append(masks, "ATime") 665 } 666 if a.MTime { 667 masks = append(masks, "MTime") 668 } 669 if a.CTime { 670 masks = append(masks, "CTime") 671 } 672 if a.INo { 673 masks = append(masks, "INo") 674 } 675 if a.Size { 676 masks = append(masks, "Size") 677 } 678 if a.Blocks { 679 masks = append(masks, "Blocks") 680 } 681 if a.BTime { 682 masks = append(masks, "BTime") 683 } 684 if a.Gen { 685 masks = append(masks, "Gen") 686 } 687 if a.DataVersion { 688 masks = append(masks, "DataVersion") 689 } 690 return fmt.Sprintf("AttrMask{with: %s}", strings.Join(masks, " ")) 691 } 692 693 // decode implements encoder.decode. 694 func (a *AttrMask) decode(b *buffer) { 695 mask := b.Read64() 696 a.Mode = mask&0x00000001 != 0 697 a.NLink = mask&0x00000002 != 0 698 a.UID = mask&0x00000004 != 0 699 a.GID = mask&0x00000008 != 0 700 a.RDev = mask&0x00000010 != 0 701 a.ATime = mask&0x00000020 != 0 702 a.MTime = mask&0x00000040 != 0 703 a.CTime = mask&0x00000080 != 0 704 a.INo = mask&0x00000100 != 0 705 a.Size = mask&0x00000200 != 0 706 a.Blocks = mask&0x00000400 != 0 707 a.BTime = mask&0x00000800 != 0 708 a.Gen = mask&0x00001000 != 0 709 a.DataVersion = mask&0x00002000 != 0 710 } 711 712 // encode implements encoder.encode. 713 func (a *AttrMask) encode(b *buffer) { 714 var mask uint64 715 if a.Mode { 716 mask |= 0x00000001 717 } 718 if a.NLink { 719 mask |= 0x00000002 720 } 721 if a.UID { 722 mask |= 0x00000004 723 } 724 if a.GID { 725 mask |= 0x00000008 726 } 727 if a.RDev { 728 mask |= 0x00000010 729 } 730 if a.ATime { 731 mask |= 0x00000020 732 } 733 if a.MTime { 734 mask |= 0x00000040 735 } 736 if a.CTime { 737 mask |= 0x00000080 738 } 739 if a.INo { 740 mask |= 0x00000100 741 } 742 if a.Size { 743 mask |= 0x00000200 744 } 745 if a.Blocks { 746 mask |= 0x00000400 747 } 748 if a.BTime { 749 mask |= 0x00000800 750 } 751 if a.Gen { 752 mask |= 0x00001000 753 } 754 if a.DataVersion { 755 mask |= 0x00002000 756 } 757 b.Write64(mask) 758 } 759 760 // Attr is a set of attributes for getattr. 761 type Attr struct { 762 Mode FileMode 763 UID UID 764 GID GID 765 NLink uint64 766 RDev uint64 767 Size uint64 768 BlockSize uint64 769 Blocks uint64 770 ATimeSeconds uint64 771 ATimeNanoSeconds uint64 772 MTimeSeconds uint64 773 MTimeNanoSeconds uint64 774 CTimeSeconds uint64 775 CTimeNanoSeconds uint64 776 BTimeSeconds uint64 777 BTimeNanoSeconds uint64 778 Gen uint64 779 DataVersion uint64 780 } 781 782 // String implements fmt.Stringer. 783 func (a Attr) String() string { 784 return fmt.Sprintf("Attr{Mode: 0o%o, UID: %d, GID: %d, NLink: %d, RDev: %d, Size: %d, BlockSize: %d, Blocks: %d, ATime: {Sec: %d, NanoSec: %d}, MTime: {Sec: %d, NanoSec: %d}, CTime: {Sec: %d, NanoSec: %d}, BTime: {Sec: %d, NanoSec: %d}, Gen: %d, DataVersion: %d}", 785 a.Mode, a.UID, a.GID, a.NLink, a.RDev, a.Size, a.BlockSize, a.Blocks, a.ATimeSeconds, a.ATimeNanoSeconds, a.MTimeSeconds, a.MTimeNanoSeconds, a.CTimeSeconds, a.CTimeNanoSeconds, a.BTimeSeconds, a.BTimeNanoSeconds, a.Gen, a.DataVersion) 786 } 787 788 // encode implements encoder.encode. 789 func (a *Attr) encode(b *buffer) { 790 b.WriteFileMode(a.Mode) 791 b.WriteUID(a.UID) 792 b.WriteGID(a.GID) 793 b.Write64(a.NLink) 794 b.Write64(a.RDev) 795 b.Write64(a.Size) 796 b.Write64(a.BlockSize) 797 b.Write64(a.Blocks) 798 b.Write64(a.ATimeSeconds) 799 b.Write64(a.ATimeNanoSeconds) 800 b.Write64(a.MTimeSeconds) 801 b.Write64(a.MTimeNanoSeconds) 802 b.Write64(a.CTimeSeconds) 803 b.Write64(a.CTimeNanoSeconds) 804 b.Write64(a.BTimeSeconds) 805 b.Write64(a.BTimeNanoSeconds) 806 b.Write64(a.Gen) 807 b.Write64(a.DataVersion) 808 } 809 810 // decode implements encoder.decode. 811 func (a *Attr) decode(b *buffer) { 812 a.Mode = b.ReadFileMode() 813 a.UID = b.ReadUID() 814 a.GID = b.ReadGID() 815 a.NLink = b.Read64() 816 a.RDev = b.Read64() 817 a.Size = b.Read64() 818 a.BlockSize = b.Read64() 819 a.Blocks = b.Read64() 820 a.ATimeSeconds = b.Read64() 821 a.ATimeNanoSeconds = b.Read64() 822 a.MTimeSeconds = b.Read64() 823 a.MTimeNanoSeconds = b.Read64() 824 a.CTimeSeconds = b.Read64() 825 a.CTimeNanoSeconds = b.Read64() 826 a.BTimeSeconds = b.Read64() 827 a.BTimeNanoSeconds = b.Read64() 828 a.Gen = b.Read64() 829 a.DataVersion = b.Read64() 830 } 831 832 // StatToAttr converts a Linux syscall stat structure to an Attr. 833 func StatToAttr(s *syscall.Stat_t, req AttrMask) (Attr, AttrMask) { 834 attr := Attr{ 835 UID: NoUID, 836 GID: NoGID, 837 } 838 if req.Mode { 839 // p9.FileMode corresponds to Linux mode_t. 840 attr.Mode = FileMode(s.Mode) 841 } 842 if req.NLink { 843 attr.NLink = uint64(s.Nlink) 844 } 845 if req.UID { 846 attr.UID = UID(s.Uid) 847 } 848 if req.GID { 849 attr.GID = GID(s.Gid) 850 } 851 if req.RDev { 852 attr.RDev = s.Dev 853 } 854 if req.ATime { 855 attr.ATimeSeconds = uint64(s.Atim.Sec) 856 attr.ATimeNanoSeconds = uint64(s.Atim.Nsec) 857 } 858 if req.MTime { 859 attr.MTimeSeconds = uint64(s.Mtim.Sec) 860 attr.MTimeNanoSeconds = uint64(s.Mtim.Nsec) 861 } 862 if req.CTime { 863 attr.CTimeSeconds = uint64(s.Ctim.Sec) 864 attr.CTimeNanoSeconds = uint64(s.Ctim.Nsec) 865 } 866 if req.Size { 867 attr.Size = uint64(s.Size) 868 } 869 if req.Blocks { 870 attr.BlockSize = uint64(s.Blksize) 871 attr.Blocks = uint64(s.Blocks) 872 } 873 874 // Use the req field because we already have it. 875 req.BTime = false 876 req.Gen = false 877 req.DataVersion = false 878 879 return attr, req 880 } 881 882 // SetAttrMask specifies a valid mask for setattr. 883 type SetAttrMask struct { 884 Permissions bool 885 UID bool 886 GID bool 887 Size bool 888 ATime bool 889 MTime bool 890 CTime bool 891 ATimeNotSystemTime bool 892 MTimeNotSystemTime bool 893 } 894 895 // IsSubsetOf returns whether s is a subset of m. 896 func (s SetAttrMask) IsSubsetOf(m SetAttrMask) bool { 897 sb := s.bitmask() 898 sm := m.bitmask() 899 return sm|sb == sm 900 } 901 902 // String implements fmt.Stringer. 903 func (s SetAttrMask) String() string { 904 var masks []string 905 if s.Permissions { 906 masks = append(masks, "Permissions") 907 } 908 if s.UID { 909 masks = append(masks, "UID") 910 } 911 if s.GID { 912 masks = append(masks, "GID") 913 } 914 if s.Size { 915 masks = append(masks, "Size") 916 } 917 if s.ATime { 918 masks = append(masks, "ATime") 919 } 920 if s.MTime { 921 masks = append(masks, "MTime") 922 } 923 if s.CTime { 924 masks = append(masks, "CTime") 925 } 926 if s.ATimeNotSystemTime { 927 masks = append(masks, "ATimeNotSystemTime") 928 } 929 if s.MTimeNotSystemTime { 930 masks = append(masks, "MTimeNotSystemTime") 931 } 932 return fmt.Sprintf("SetAttrMask{with: %s}", strings.Join(masks, " ")) 933 } 934 935 // Empty returns true if no fields are masked. 936 func (s SetAttrMask) Empty() bool { 937 return !s.Permissions && !s.UID && !s.GID && !s.Size && !s.ATime && !s.MTime && !s.CTime && !s.ATimeNotSystemTime && !s.MTimeNotSystemTime 938 } 939 940 // decode implements encoder.decode. 941 func (s *SetAttrMask) decode(b *buffer) { 942 mask := b.Read32() 943 s.Permissions = mask&0x00000001 != 0 944 s.UID = mask&0x00000002 != 0 945 s.GID = mask&0x00000004 != 0 946 s.Size = mask&0x00000008 != 0 947 s.ATime = mask&0x00000010 != 0 948 s.MTime = mask&0x00000020 != 0 949 s.CTime = mask&0x00000040 != 0 950 s.ATimeNotSystemTime = mask&0x00000080 != 0 951 s.MTimeNotSystemTime = mask&0x00000100 != 0 952 } 953 954 func (s SetAttrMask) bitmask() uint32 { 955 var mask uint32 956 if s.Permissions { 957 mask |= 0x00000001 958 } 959 if s.UID { 960 mask |= 0x00000002 961 } 962 if s.GID { 963 mask |= 0x00000004 964 } 965 if s.Size { 966 mask |= 0x00000008 967 } 968 if s.ATime { 969 mask |= 0x00000010 970 } 971 if s.MTime { 972 mask |= 0x00000020 973 } 974 if s.CTime { 975 mask |= 0x00000040 976 } 977 if s.ATimeNotSystemTime { 978 mask |= 0x00000080 979 } 980 if s.MTimeNotSystemTime { 981 mask |= 0x00000100 982 } 983 return mask 984 } 985 986 // encode implements encoder.encode. 987 func (s *SetAttrMask) encode(b *buffer) { 988 b.Write32(s.bitmask()) 989 } 990 991 // SetAttr specifies a set of attributes for a setattr. 992 type SetAttr struct { 993 Permissions FileMode 994 UID UID 995 GID GID 996 Size uint64 997 ATimeSeconds uint64 998 ATimeNanoSeconds uint64 999 MTimeSeconds uint64 1000 MTimeNanoSeconds uint64 1001 } 1002 1003 // String implements fmt.Stringer. 1004 func (s SetAttr) String() string { 1005 return fmt.Sprintf("SetAttr{Permissions: 0o%o, UID: %d, GID: %d, Size: %d, ATime: {Sec: %d, NanoSec: %d}, MTime: {Sec: %d, NanoSec: %d}}", s.Permissions, s.UID, s.GID, s.Size, s.ATimeSeconds, s.ATimeNanoSeconds, s.MTimeSeconds, s.MTimeNanoSeconds) 1006 } 1007 1008 // decode implements encoder.decode. 1009 func (s *SetAttr) decode(b *buffer) { 1010 s.Permissions = b.ReadPermissions() 1011 s.UID = b.ReadUID() 1012 s.GID = b.ReadGID() 1013 s.Size = b.Read64() 1014 s.ATimeSeconds = b.Read64() 1015 s.ATimeNanoSeconds = b.Read64() 1016 s.MTimeSeconds = b.Read64() 1017 s.MTimeNanoSeconds = b.Read64() 1018 } 1019 1020 // encode implements encoder.encode. 1021 func (s *SetAttr) encode(b *buffer) { 1022 b.WritePermissions(s.Permissions) 1023 b.WriteUID(s.UID) 1024 b.WriteGID(s.GID) 1025 b.Write64(s.Size) 1026 b.Write64(s.ATimeSeconds) 1027 b.Write64(s.ATimeNanoSeconds) 1028 b.Write64(s.MTimeSeconds) 1029 b.Write64(s.MTimeNanoSeconds) 1030 } 1031 1032 // Apply applies this to the given Attr. 1033 func (a *Attr) Apply(mask SetAttrMask, attr SetAttr) { 1034 if mask.Permissions { 1035 a.Mode = a.Mode&^permissionsMask | (attr.Permissions & permissionsMask) 1036 } 1037 if mask.UID { 1038 a.UID = attr.UID 1039 } 1040 if mask.GID { 1041 a.GID = attr.GID 1042 } 1043 if mask.Size { 1044 a.Size = attr.Size 1045 } 1046 if mask.ATime { 1047 a.ATimeSeconds = attr.ATimeSeconds 1048 a.ATimeNanoSeconds = attr.ATimeNanoSeconds 1049 } 1050 if mask.MTime { 1051 a.MTimeSeconds = attr.MTimeSeconds 1052 a.MTimeNanoSeconds = attr.MTimeNanoSeconds 1053 } 1054 } 1055 1056 // Dirent is used for readdir. 1057 type Dirent struct { 1058 // QID is the entry QID. 1059 QID QID 1060 1061 // Offset is the offset in the directory. 1062 // 1063 // This will be communicated back the original caller. 1064 Offset uint64 1065 1066 // Type is the 9P type. 1067 Type QIDType 1068 1069 // Name is the name of the entry (i.e. basename). 1070 Name string 1071 } 1072 1073 // String implements fmt.Stringer. 1074 func (d Dirent) String() string { 1075 return fmt.Sprintf("Dirent{QID: %d, Offset: %d, Type: 0x%X, Name: %s}", d.QID, d.Offset, d.Type, d.Name) 1076 } 1077 1078 // decode implements encoder.decode. 1079 func (d *Dirent) decode(b *buffer) { 1080 d.QID.decode(b) 1081 d.Offset = b.Read64() 1082 d.Type = b.ReadQIDType() 1083 d.Name = b.ReadString() 1084 } 1085 1086 // encode implements encoder.encode. 1087 func (d *Dirent) encode(b *buffer) { 1088 d.QID.encode(b) 1089 b.Write64(d.Offset) 1090 b.WriteQIDType(d.Type) 1091 b.WriteString(d.Name) 1092 } 1093 1094 // AllocateMode are possible modes to p9.File.Allocate(). 1095 type AllocateMode struct { 1096 KeepSize bool 1097 PunchHole bool 1098 NoHideStale bool 1099 CollapseRange bool 1100 ZeroRange bool 1101 InsertRange bool 1102 Unshare bool 1103 } 1104 1105 // ToAllocateMode returns an AllocateMode from a fallocate(2) mode. 1106 func ToAllocateMode(mode uint64) AllocateMode { 1107 return AllocateMode{ 1108 KeepSize: mode&unix.FALLOC_FL_KEEP_SIZE != 0, 1109 PunchHole: mode&unix.FALLOC_FL_PUNCH_HOLE != 0, 1110 NoHideStale: mode&unix.FALLOC_FL_NO_HIDE_STALE != 0, 1111 CollapseRange: mode&unix.FALLOC_FL_COLLAPSE_RANGE != 0, 1112 ZeroRange: mode&unix.FALLOC_FL_ZERO_RANGE != 0, 1113 InsertRange: mode&unix.FALLOC_FL_INSERT_RANGE != 0, 1114 Unshare: mode&unix.FALLOC_FL_UNSHARE_RANGE != 0, 1115 } 1116 } 1117 1118 // ToLinux converts to a value compatible with fallocate(2)'s mode. 1119 func (a *AllocateMode) ToLinux() uint32 { 1120 rv := uint32(0) 1121 if a.KeepSize { 1122 rv |= unix.FALLOC_FL_KEEP_SIZE 1123 } 1124 if a.PunchHole { 1125 rv |= unix.FALLOC_FL_PUNCH_HOLE 1126 } 1127 if a.NoHideStale { 1128 rv |= unix.FALLOC_FL_NO_HIDE_STALE 1129 } 1130 if a.CollapseRange { 1131 rv |= unix.FALLOC_FL_COLLAPSE_RANGE 1132 } 1133 if a.ZeroRange { 1134 rv |= unix.FALLOC_FL_ZERO_RANGE 1135 } 1136 if a.InsertRange { 1137 rv |= unix.FALLOC_FL_INSERT_RANGE 1138 } 1139 if a.Unshare { 1140 rv |= unix.FALLOC_FL_UNSHARE_RANGE 1141 } 1142 return rv 1143 } 1144 1145 // decode implements encoder.decode. 1146 func (a *AllocateMode) decode(b *buffer) { 1147 mask := b.Read32() 1148 a.KeepSize = mask&0x01 != 0 1149 a.PunchHole = mask&0x02 != 0 1150 a.NoHideStale = mask&0x04 != 0 1151 a.CollapseRange = mask&0x08 != 0 1152 a.ZeroRange = mask&0x10 != 0 1153 a.InsertRange = mask&0x20 != 0 1154 a.Unshare = mask&0x40 != 0 1155 } 1156 1157 // encode implements encoder.encode. 1158 func (a *AllocateMode) encode(b *buffer) { 1159 mask := uint32(0) 1160 if a.KeepSize { 1161 mask |= 0x01 1162 } 1163 if a.PunchHole { 1164 mask |= 0x02 1165 } 1166 if a.NoHideStale { 1167 mask |= 0x04 1168 } 1169 if a.CollapseRange { 1170 mask |= 0x08 1171 } 1172 if a.ZeroRange { 1173 mask |= 0x10 1174 } 1175 if a.InsertRange { 1176 mask |= 0x20 1177 } 1178 if a.Unshare { 1179 mask |= 0x40 1180 } 1181 b.Write32(mask) 1182 } 1183 1184 // FullStat is used in the result of a MultiGetAttr call. 1185 type FullStat struct { 1186 QID QID 1187 Valid AttrMask 1188 Attr Attr 1189 } 1190 1191 // String implements fmt.Stringer. 1192 func (f *FullStat) String() string { 1193 return fmt.Sprintf("FullStat{QID: %v, Valid: %v, Attr: %v}", f.QID, f.Valid, f.Attr) 1194 } 1195 1196 // decode implements encoder.decode. 1197 func (f *FullStat) decode(b *buffer) { 1198 f.QID.decode(b) 1199 f.Valid.decode(b) 1200 f.Attr.decode(b) 1201 } 1202 1203 // encode implements encoder.encode. 1204 func (f *FullStat) encode(b *buffer) { 1205 f.QID.encode(b) 1206 f.Valid.encode(b) 1207 f.Attr.encode(b) 1208 }