github.com/vmware/go-vcloud-director/v2@v2.24.0/internal/udf/reader.go (about) 1 package udf 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7 "io/fs" 8 "path/filepath" 9 "time" 10 11 "golang.org/x/text/encoding/charmap" 12 "golang.org/x/text/encoding/unicode" 13 "golang.org/x/text/transform" 14 ) 15 16 func Open(reader io.ReaderAt) (r *ImageReader, err error) { 17 defer func() { 18 if fatalErr := recover(); fatalErr != nil { 19 err = fmt.Errorf("%v", fatalErr) 20 } 21 }() 22 r = &ImageReader{inner: reader} 23 24 r.cdromVolumeDescriptors = r.readCdromVolumeDescriptorSequence(cdromVolumeDescriptorSectorNumber) 25 26 // Validate image is UDF 27 if !r.cdromVolumeDescriptors.hasAnyIdentifier(cdromVolumeIdentifierNSR02, cdromVolumeIdentifierNSR03) { 28 err = fmt.Errorf("unsupported image format") 29 return 30 } 31 32 r.anchorVolumeDescriptor = r.readDescriptorFromSectorWithTag( 33 anchorVolumeDescriptorSectorNumber, tagAnchorVolumeDescriptorPointer).(*AnchorVolumeDescriptorPointer) 34 r.mainVolumeDescriptors = r.readDescriptorSequence(&r.anchorVolumeDescriptor.MainVolumeDescriptorSequence) 35 r.primaryVolume = r.mainVolumeDescriptors.get(tagPrimaryVolumeDescriptor).(*PrimaryVolumeDescriptor) 36 r.partition = r.mainVolumeDescriptors.get(tagPartitionDescriptor).(*PartitionDescriptor) 37 r.logicalVolume = r.mainVolumeDescriptors.get(tagLogicalVolumeDescriptor).(*LogicalVolumeDescriptor) 38 r.fileSet = r.readDescriptorFromSectorWithTag(int64(r.partition.PartitionStartingLocation), tagFileSetDescriptor).(*FileSetDescriptor) 39 return 40 } 41 42 type descriptorReader interface { 43 Descriptor 44 read(reader *bufferReader) 45 } 46 47 type ImageReader struct { 48 inner io.ReaderAt 49 cdromVolumeDescriptors CdromDescriptorList 50 anchorVolumeDescriptor *AnchorVolumeDescriptorPointer 51 mainVolumeDescriptors DescriptorList 52 primaryVolume *PrimaryVolumeDescriptor 53 partition *PartitionDescriptor 54 logicalVolume *LogicalVolumeDescriptor 55 fileSet *FileSetDescriptor 56 } 57 58 func (r *ImageReader) RootDir() (fi *FileInfo, err error) { 59 defer func() { 60 if fatalErr := recover(); fatalErr != nil { 61 err = fmt.Errorf("unable to read UDF root directory: %v", fatalErr) 62 } 63 }() 64 partitionStart := int64(r.partition.PartitionStartingLocation) 65 fileEntrySector := partitionStart + int64(r.fileSet.RootDirectoryICB.Location) 66 fileEntry := r.readDescriptorFromSectorWithTag(fileEntrySector, tagFileEntry).(*FileEntryDescriptor) 67 fi = &FileInfo{ 68 entry: fileEntry, 69 logicalVolume: r.logicalVolume, 70 } 71 return 72 } 73 74 func (r *ImageReader) ReadDir(parent *FileInfo) (children []FileInfo, err error) { 75 defer func() { 76 if fatalErr := recover(); fatalErr != nil { 77 err = fmt.Errorf("unable to read UDF directory: %v", fatalErr) 78 } 79 }() 80 81 if !parent.IsDir() { 82 err = fmt.Errorf("entry %s is not a directory", parent.Name()) 83 return 84 } 85 86 if len(parent.entry.AllocationDescriptors) == 0 { 87 children = []FileInfo{} 88 return 89 } 90 91 children = make([]FileInfo, 0, 8) 92 93 for idx := range parent.entry.AllocationDescriptors { 94 allocDesc := &parent.entry.AllocationDescriptors[idx] 95 bufSize := int(allocDesc.Length) 96 partitionStart := int64(r.partition.PartitionStartingLocation) 97 fileBufReader := r.readSectors(partitionStart+int64(allocDesc.Location), (bufSize+sectorSize-1)/sectorSize) 98 99 for fileBufReader.off < bufSize { 100 fid := r.readDescriptorWithTag(fileBufReader, tagFileIdentifierDescriptor).(*FileIdentifierDescriptor) 101 if len(fid.FileIdentifier) > 0 { 102 fileEntrySector := partitionStart + int64(fid.ICB.Location) 103 fileEntry := r.readDescriptorFromSectorWithTag(fileEntrySector, tagFileEntry).(*FileEntryDescriptor) 104 105 var filePath string 106 if parent.IsRoot() { 107 filePath = fid.FileIdentifier 108 } else { 109 filePath = filepath.Join(parent.path, fid.FileIdentifier) 110 } 111 112 children = append(children, FileInfo{ 113 entry: fileEntry, 114 fid: fid, 115 parent: parent, 116 path: filePath, 117 }) 118 } 119 } 120 } 121 122 return 123 } 124 125 func (r *ImageReader) NewFileReader(file *FileInfo) (fileReader io.Reader, err error) { 126 if file.IsDir() { 127 err = fmt.Errorf("entry %s is not a file", file.Name()) 128 return 129 } 130 131 defer func() { 132 if fatalErr := recover(); fatalErr != nil { 133 err = fmt.Errorf("unable to open UDF file: %v", fatalErr) 134 } 135 }() 136 137 partitionStart := int64(r.partition.PartitionStartingLocation) 138 readers := make([]io.Reader, len(file.entry.AllocationDescriptors)) 139 140 for idx := range file.entry.AllocationDescriptors { 141 allocDesc := &file.entry.AllocationDescriptors[idx] 142 location := int64(allocDesc.Location) 143 offset := sectorSize * (location + partitionStart) 144 readers[idx] = io.NewSectionReader(r.inner, offset, int64(allocDesc.Length)) 145 } 146 147 fileReader = io.MultiReader(readers...) 148 return 149 } 150 151 func (r *ImageReader) readDescriptorSequence(ref *Extent) DescriptorList { 152 descriptors := make(DescriptorList, 0, 8) 153 for sector := int64(ref.Location); ; sector++ { 154 descriptor := r.readDescriptorFromSector(sector) 155 descriptors = append(descriptors, descriptor) 156 if descriptor.GetIdentifier() == tagTerminatingDescriptor { 157 break 158 } 159 } 160 return descriptors 161 } 162 163 func (r *ImageReader) readDescriptor(bufferReader *bufferReader) Descriptor { 164 tagId := bufferReader.peekUint16() 165 descriptor := NewDescriptor(tagId) 166 descriptor.(descriptorReader).read(bufferReader) 167 return descriptor 168 } 169 170 func (r *ImageReader) readDescriptorWithTag(bufferReader *bufferReader, tagId int) Descriptor { 171 descriptor := r.readDescriptor(bufferReader) 172 if descriptor.GetIdentifier() != tagId { 173 panic(fmt.Errorf("expected descriptor with tag ID %d but was %d", tagId, descriptor.GetIdentifier())) 174 } 175 return descriptor 176 } 177 178 func (r *ImageReader) readDescriptorFromSector(sector int64) Descriptor { 179 return r.readDescriptor(r.readSector(sector)) 180 } 181 182 func (r *ImageReader) readDescriptorFromSectorWithTag(sector int64, tagId int) Descriptor { 183 descriptor := r.readDescriptorFromSector(sector) 184 if descriptor.GetIdentifier() != tagId { 185 panic(fmt.Errorf("expected descriptor with tag ID %d but was %d at sector %d", 186 tagId, descriptor.GetIdentifier(), sector)) 187 } 188 return descriptor 189 } 190 191 func (r *ImageReader) readCdromVolumeDescriptorSequence(sector int64) CdromDescriptorList { 192 descriptors := make(CdromDescriptorList, 0, 8) 193 for n := sector; ; n++ { 194 descriptor := r.readCdromVolumeDescriptorFromSector(n) 195 descriptors = append(descriptors, descriptor) 196 if descriptor.GetHeader().Identifier == cdromVolumeIdentifierTEA01 { 197 break 198 } 199 } 200 return descriptors 201 } 202 203 func (r *ImageReader) readCdromVolumeDescriptor(bufferReader *bufferReader) CdromDescriptor { 204 header := CdromVolumeDescriptorHeader{} 205 header.read(bufferReader) 206 207 switch header.Identifier { 208 case cdromVolumeIdentifierBEA01: 209 return &CdromExtendedAreaVolumeDescriptor{ 210 Header: header, 211 } 212 case cdromVolumeIdentifierBOOT2: 213 return &CdromBootVolumeDescriptor{ 214 Header: header, 215 } 216 case cdromVolumeIdentifierCD001: 217 return &CdromCdwVolumeDescriptor{ 218 Header: header, 219 } 220 case cdromVolumeIdentifierCDW02: 221 return &CdromCdwVolumeDescriptor{ 222 Header: header, 223 } 224 case cdromVolumeIdentifierNSR02: 225 return &CdromNsrVolumeDescriptor{ 226 Header: header, 227 } 228 case cdromVolumeIdentifierNSR03: 229 return &CdromNsrVolumeDescriptor{ 230 Header: header, 231 } 232 case cdromVolumeIdentifierTEA01: 233 return &CdromTerminalVolumeDescriptor{ 234 Header: header, 235 } 236 default: 237 panic(fmt.Sprintf("unrecognized file system '%s'", header.Identifier)) 238 } 239 } 240 241 func (r *ImageReader) readCdromVolumeDescriptorFromSector(sector int64) CdromDescriptor { 242 return r.readCdromVolumeDescriptor(r.readSector(sector)) 243 } 244 245 func (r *ImageReader) readSector(sector int64) *bufferReader { 246 return r.read(sector*sectorSize, sectorSize) 247 } 248 249 func (r *ImageReader) readSectors(sector int64, count int) *bufferReader { 250 return r.read(sector*sectorSize, sectorSize*count) 251 } 252 253 func (r *ImageReader) read(offset int64, size int) *bufferReader { 254 data := make([]byte, size) 255 if n, err := r.inner.ReadAt(data, offset); err != nil { 256 panic(err) 257 } else if n != size { 258 panic(io.ErrUnexpectedEOF) 259 } 260 return &bufferReader{buf: data} 261 } 262 263 func (e *Extent) read(reader *bufferReader) { 264 e.Length = reader.readUint32() 265 e.Location = reader.readUint32() 266 } 267 268 func (e *ExtentLong) read(reader *bufferReader) { 269 e.Length = reader.readUint32() 270 e.Location = reader.readUint48() 271 reader.skipBytes(6) // Reserved 272 } 273 274 func (e *EntityID) read(reader *bufferReader) { 275 e.Flags = reader.readUint8() 276 e.Identifier = reader.readString(23) 277 e.IdentifierSuffix = reader.readString(8) 278 } 279 280 func (iu *ImplementationUse) read(reader *bufferReader, size int) { 281 iu.Entity.read(reader) 282 size = size - entityIdSize // ImplementationUse - EntityID 283 if size > 0 { 284 iu.Implementation = reader.readBytes(size) 285 } 286 } 287 288 func (c *Charspec) read(reader *bufferReader) { 289 c.CharacterSetType = reader.readUint8() 290 c.CharacterSetInfo = reader.readBytes(63) 291 } 292 293 func (tag *DescriptorTag) read(reader *bufferReader) { 294 tag.TagIdentifier = reader.readUint16() 295 tag.DescriptorVersion = reader.readUint16() 296 tag.TagChecksum = reader.readUint8() 297 reader.skipBytes(1) // Reserved 298 tag.TagSerialNumber = reader.readUint16() 299 tag.DescriptorCRC = reader.readUint16() 300 tag.DescriptorCRCLength = reader.readUint16() 301 tag.TagLocation = reader.readUint32() 302 } 303 304 func (d *AnchorVolumeDescriptorPointer) read(reader *bufferReader) { 305 d.Tag.read(reader) 306 d.MainVolumeDescriptorSequence.read(reader) 307 d.ReserveVolumeDescriptorSequence.read(reader) 308 reader.skipBytes(480) // Reserved 309 } 310 311 func (d *VolumeDescriptorPointer) read(reader *bufferReader) { 312 d.Tag.read(reader) 313 d.VolumeDescriptorSequenceNumber = reader.readUint32() 314 d.NextVolumeDescriptorSequenceExtent.read(reader) 315 // This field shall be reserved for future standardisation and all bytes shall be set to #00 316 reader.skipBytes(484) 317 } 318 319 func (d *PrimaryVolumeDescriptor) read(reader *bufferReader) { 320 d.Tag.read(reader) 321 d.VolumeDescriptorSequenceNumber = reader.readUint32() 322 d.PrimaryVolumeDescriptorNumber = reader.readUint32() 323 d.VolumeIdentifier = reader.readDString(32) 324 d.VolumeSequenceNumber = reader.readUint16() 325 d.MaximumVolumeSequenceNumber = reader.readUint16() 326 d.InterchangeLevel = reader.readUint16() 327 d.MaximumInterchangeLevel = reader.readUint16() 328 d.CharacterSetList = reader.readUint32() 329 d.MaximumCharacterSetList = reader.readUint32() 330 d.VolumeSetIdentifier = reader.readDString(128) 331 d.DescriptorCharacterSet.read(reader) 332 d.ExplanatoryCharacterSet.read(reader) 333 d.VolumeAbstract.read(reader) 334 d.VolumeCopyrightNoticeExtent.read(reader) 335 d.ApplicationIdentifier.read(reader) 336 d.RecordingDateTime = reader.readTimestamp() 337 d.ImplementationIdentifier.read(reader) 338 d.ImplementationUse = reader.readBytes(64) 339 d.PredecessorVolumeDescriptorSequenceLocation = reader.readUint32() 340 d.Flags = reader.readUint16() 341 reader.skipBytes(22) // Reserved 342 } 343 344 func (d *ImplementationUseVolumeDescriptor) read(reader *bufferReader) { 345 d.Tag.read(reader) 346 d.VolumeDescriptorSequenceNumber = reader.readUint32() 347 d.ImplementationIdentifier.read(reader) 348 d.ImplementationUse.read(reader) 349 } 350 351 func (lvi *LVInformation) read(reader *bufferReader) { 352 lvi.LVICharset.read(reader) 353 lvi.LogicalVolumeIdentifier = reader.readDString(128) 354 lvi.LVInfo1 = reader.readDString(36) 355 lvi.LVInfo2 = reader.readDString(36) 356 lvi.LVInfo3 = reader.readDString(36) 357 lvi.ImplementationID.read(reader) 358 lvi.ImplementationUse = reader.readBytes(128) 359 } 360 361 func (d *PartitionDescriptor) read(reader *bufferReader) { 362 d.Tag.read(reader) 363 d.VolumeDescriptorSequenceNumber = reader.readUint32() 364 d.PartitionFlags = reader.readUint16() 365 d.PartitionNumber = reader.readUint16() 366 d.PartitionContents.read(reader) 367 d.PartitionContentsUse = reader.readBytes(128) 368 d.AccessType = reader.readUint32() 369 d.PartitionStartingLocation = reader.readUint32() 370 d.PartitionLength = reader.readUint32() 371 d.ImplementationIdentifier.read(reader) 372 d.ImplementationUse = reader.readBytes(128) 373 reader.skipBytes(156) 374 } 375 376 func (d *LogicalVolumeDescriptor) read(reader *bufferReader) { 377 d.Tag.read(reader) 378 d.VolumeDescriptorSequenceNumber = reader.readUint32() 379 d.DescriptorCharacterSet.read(reader) 380 d.LogicalVolumeIdentifier = reader.readDString(128) 381 d.LogicalBlockSize = reader.readUint32() 382 d.DomainIdentifier.read(reader) 383 d.LogicalVolumeContentsUse = reader.readBytes(16) 384 d.MapTableLength = reader.readUint32() 385 d.NumberOfPartitionMaps = reader.readUint32() 386 d.ImplementationIdentifier.read(reader) 387 d.ImplementationUse = reader.readBytes(128) 388 d.IntegritySequenceExtent.read(reader) 389 d.PartitionMaps = make([]PartitionMap, d.NumberOfPartitionMaps) 390 for idx := 0; idx < int(d.NumberOfPartitionMaps); idx++ { 391 d.PartitionMaps[idx].read(reader) 392 } 393 } 394 395 func (d *LogicalVolumeIntegrityDescriptor) read(reader *bufferReader) { 396 d.Tag.read(reader) 397 d.RecordingDateTime = reader.readTimestamp() 398 d.IntegrityType = reader.readUint32() 399 d.NextIntegrityExtent.read(reader) 400 d.LogicalVolumeContentsUse.read(reader) 401 d.NumberOfPartitions = reader.readUint32() 402 d.LengthOfImplementationUse = reader.readUint32() 403 d.FreeSpaceTable = make([]uint32, d.NumberOfPartitions) 404 for idx := range d.FreeSpaceTable { 405 d.FreeSpaceTable[idx] = reader.readUint32() 406 } 407 d.SizeTable = make([]uint32, d.NumberOfPartitions) 408 for idx := range d.SizeTable { 409 d.SizeTable[idx] = reader.readUint32() 410 } 411 d.ImplementationUse.read(reader, int(d.LengthOfImplementationUse)) 412 } 413 414 func (h *LogicalVolumeHeaderDescriptor) read(reader *bufferReader) { 415 h.UniqueID = reader.readUint64() 416 reader.skipBytes(24) // Reserved 417 } 418 419 func (pm *PartitionMap) read(reader *bufferReader) { 420 pm.PartitionMapType = reader.readUint8() 421 if pm.PartitionMapType != 1 { 422 panic(fmt.Sprintf("expected partition map 1 but got %d", pm.PartitionMapType)) 423 } 424 pm.PartitionMapLength = reader.readUint8() 425 if pm.PartitionMapLength != 6 { 426 panic(fmt.Sprintf("expected partition map 1 to be 6 bytes long but was %d", pm.PartitionMapLength)) 427 } 428 pm.VolumeSequenceNumber = reader.readUint16() 429 pm.PartitionNumber = reader.readUint16() 430 } 431 432 func (d *UnallocatedSpaceDescriptor) read(reader *bufferReader) { 433 d.Tag.read(reader) 434 d.VolumeDescriptorSequenceNumber = reader.readUint32() 435 d.NumberOfAllocationDescriptors = reader.readUint32() 436 d.AllocationDescriptors = make([]Extent, d.NumberOfAllocationDescriptors) 437 for idx := 0; idx < int(d.NumberOfAllocationDescriptors); idx++ { 438 d.AllocationDescriptors[idx].read(reader) 439 } 440 } 441 442 func (d *TerminatingDescriptor) read(reader *bufferReader) { 443 d.Tag.read(reader) 444 reader.skipBytes(496) // Reserved 445 } 446 447 func (d *FileSetDescriptor) read(reader *bufferReader) { 448 d.Tag.read(reader) 449 d.RecordingDateTime = reader.readTimestamp() 450 d.InterchangeLevel = reader.readUint16() 451 d.MaximumInterchangeLevel = reader.readUint16() 452 d.CharacterSetList = reader.readUint32() 453 d.MaximumCharacterSetList = reader.readUint32() 454 d.FileSetNumber = reader.readUint32() 455 d.FileSetDescriptorNumber = reader.readUint32() 456 d.LogicalVolumeIdentifierCharacterSet.read(reader) 457 d.LogicalVolumeIdentifier = reader.readDString(128) 458 d.FileSetCharacterSet.read(reader) 459 d.FileSetIdentifier = reader.readDString(32) 460 d.CopyrightFileIdentifier = reader.readDString(32) 461 d.AbstractFileIdentifier = reader.readDString(32) 462 d.RootDirectoryICB.read(reader) 463 d.DomainIdentifier.read(reader) 464 d.NextExtent.read(reader) 465 d.SystemStreamDirectoryICB.read(reader) 466 reader.skipBytes(32) // Reserved 467 } 468 469 func (d *FileEntryDescriptor) read(reader *bufferReader) { 470 d.Tag.read(reader) 471 d.ICBTag.read(reader) 472 d.Uid = reader.readUint32() 473 d.Gid = reader.readUint32() 474 d.Permissions = FileMode(reader.readUint32()) 475 d.FileLinkCount = reader.readUint16() 476 d.RecordFormat = reader.readUint8() 477 d.RecordDisplayAttributes = reader.readUint8() 478 d.RecordLength = reader.readUint32() 479 d.InformationLength = reader.readUint64() 480 d.LogicalBlocksRecorded = reader.readUint64() 481 d.AccessTime = reader.readTimestamp() 482 d.ModificationTime = reader.readTimestamp() 483 d.AttributeTime = reader.readTimestamp() 484 d.Checkpoint = reader.readUint32() 485 d.ExtendedAttributeICB.read(reader) 486 d.ImplementationIdentifier.read(reader) 487 d.UniqueID = reader.readUint64() 488 d.LengthOfExtendedAttributes = reader.readUint32() 489 d.LengthOfAllocationDescriptors = reader.readUint32() 490 d.ExtendedAttributes = reader.readBytes(int(d.LengthOfExtendedAttributes)) 491 d.AllocationDescriptors = make([]Extent, d.LengthOfAllocationDescriptors/8) 492 for i := range d.AllocationDescriptors { 493 d.AllocationDescriptors[i].read(reader) 494 } 495 } 496 497 func (icb *ICBTag) read(reader *bufferReader) { 498 icb.PriorRecordedNumberOfDirectEntries = reader.readUint32() 499 icb.StrategyType = reader.readUint16() 500 icb.StrategyParameter = reader.readUint16() 501 icb.MaximumNumberOfEntries = reader.readUint16() 502 reader.skipBytes(1) 503 icb.FileType = reader.readUint8() 504 icb.ParentICBLocation.read(reader) 505 icb.Flags = reader.readUint16() 506 } 507 508 func (lba *LogicalBlockAddress) read(reader *bufferReader) { 509 lba.LogicalBlockNumber = reader.readUint32() 510 lba.PartitionReferenceNumber = reader.readUint16() 511 } 512 513 func (d *FileIdentifierDescriptor) read(reader *bufferReader) { 514 start := reader.off 515 d.Tag.read(reader) 516 d.FileVersionNumber = reader.readUint16() 517 d.FileCharacteristics = FileCharacteristics(reader.readUint8()) 518 d.LengthOfFileIdentifier = reader.readUint8() 519 d.ICB.read(reader) 520 d.LengthOfImplementationUse = reader.readUint16() 521 d.ImplementationUse = reader.readBytes(int(d.LengthOfImplementationUse)) 522 d.FileIdentifier = reader.readDCharacters(int(d.LengthOfFileIdentifier)) 523 524 // Padding: 4 x ip((L_FI+L_IU+38+3)/4) - (L_FI+L_IU+38) bytes long and shall contain all #00 bytes. 525 // L_FI: Length of File Identifier 526 // L_IU: Length of Implementation Use 527 currentSize := reader.off - start 528 paddingLen := 4*((currentSize+3)/4) - currentSize 529 reader.skipBytes(paddingLen) 530 } 531 532 func (d *CdromVolumeDescriptorHeader) read(reader *bufferReader) { 533 d.Type = reader.readUint8() 534 d.Identifier = string(reader.readBytes(5)) 535 d.Version = reader.readUint8() 536 } 537 538 type bufferReader struct { 539 off int 540 buf []byte 541 } 542 543 func (r *bufferReader) eof() bool { 544 return r.off >= len(r.buf) 545 } 546 547 func (r *bufferReader) skipBytes(len int) { 548 r.off += len 549 } 550 551 func (r *bufferReader) readBytes(len int) []byte { 552 start := r.off 553 r.off += len 554 return r.buf[start:r.off] 555 } 556 557 func (r *bufferReader) readInt8() int8 { 558 return int8(r.readUint8()) 559 } 560 561 func (r *bufferReader) readUint8() uint8 { 562 start := r.off 563 r.off += 1 564 return r.buf[start] 565 } 566 567 func (r *bufferReader) readInt16() int16 { 568 return int16(r.readUint16()) 569 } 570 571 func (r *bufferReader) readUint16() uint16 { 572 start := r.off 573 r.off += 2 574 return binary.LittleEndian.Uint16(r.buf[start:r.off]) 575 } 576 577 func (r *bufferReader) peekUint16() uint16 { 578 return binary.LittleEndian.Uint16(r.buf[r.off : r.off+2]) 579 } 580 581 func (r *bufferReader) readInt32() int32 { 582 return int32(r.readUint32()) 583 } 584 585 func (r *bufferReader) readUint32() uint32 { 586 start := r.off 587 r.off += 4 588 return binary.LittleEndian.Uint32(r.buf[start:r.off]) 589 } 590 591 func (r *bufferReader) readUint48() uint64 { 592 start := r.off 593 r.off += 6 594 data := make([]byte, 8) 595 copy(data, r.buf[start:r.off]) 596 return binary.LittleEndian.Uint64(data) 597 } 598 599 func (r *bufferReader) readInt64() int64 { 600 return int64(r.readUint64()) 601 } 602 603 func (r *bufferReader) readUint64() uint64 { 604 start := r.off 605 r.off += 8 606 return binary.LittleEndian.Uint64(r.buf[start:r.off]) 607 } 608 609 func (r *bufferReader) readString(size int) string { 610 if size == 0 { 611 return "" 612 } 613 start := r.off 614 r.off += size 615 return string(r.buf[start:r.off]) 616 } 617 618 func (r *bufferReader) readDString(size int) string { 619 if size == 0 { 620 return "" 621 } 622 start := r.off 623 r.off += size 624 length := int(r.buf[r.off-1]) 625 if length == 0 { 626 return "" 627 } 628 629 // The CompressionID shall identify the compression algorithm used to compress the CompressedBitStream field. 630 // 8: Value indicates there are 8 bits per character in the CompressedBitStream. 631 // 16: Value indicates there are 16 bits per character in the CompressedBitStream. 632 compressionId := r.buf[start] 633 if compressionId != 8 { 634 panic("expecting character length to be 8 bit long") 635 } 636 637 return string(r.buf[start+1 : start+length]) 638 } 639 640 func (r *bufferReader) readDCharacters(length int) string { 641 if length == 0 { 642 return "" 643 } 644 encodingType := r.readUint8() 645 length-- 646 switch encodingType { 647 case dcharEncodingType8: 648 win1252Dec := charmap.Windows1252.NewDecoder() 649 s, _, err := transform.Bytes(win1252Dec, r.readBytes(length)) 650 if err != nil { 651 panic(err) 652 } 653 return string(s) 654 case dcharEncodingType16: 655 utf16Dec := unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM).NewDecoder() 656 s, _, err := transform.Bytes(utf16Dec, r.readBytes(length)) 657 if err != nil { 658 panic(err) 659 } 660 return string(s) 661 default: 662 panic(fmt.Sprintf("unsupported string encoding type %d", encodingType)) 663 } 664 } 665 666 func (r *bufferReader) readTimestamp() time.Time { 667 r.skipBytes(2) // TypeAndTimezone 668 year := r.readUint16() 669 month := r.readUint8() 670 day := r.readUint8() 671 hour := r.readUint8() 672 minute := r.readUint8() 673 second := r.readUint8() 674 r.skipBytes(3) // Centiseconds+HundredsofMicroseconds+Microseconds 675 return time.Date(int(year), time.Month(month), int(day), int(hour), int(minute), int(second), 0, time.UTC) 676 } 677 678 type FileInfo struct { 679 fid *FileIdentifierDescriptor 680 logicalVolume *LogicalVolumeDescriptor 681 entry *FileEntryDescriptor 682 parent *FileInfo 683 path string 684 } 685 686 func (f *FileInfo) Name() string { 687 if f.IsRoot() { 688 return f.logicalVolume.LogicalVolumeIdentifier 689 } else { 690 return f.fid.FileIdentifier 691 } 692 } 693 694 func (f *FileInfo) Path() string { 695 return f.path 696 } 697 698 func (f *FileInfo) Size() int64 { 699 return int64(f.entry.InformationLength) 700 } 701 702 func (f *FileInfo) Mode() FileMode { 703 return f.entry.Permissions 704 } 705 706 func (f *FileInfo) FileMode() fs.FileMode { 707 mode := FromFileMode(f.entry.Permissions) 708 if f.IsDir() { 709 mode |= fs.ModeDir 710 } 711 return mode 712 } 713 714 func (f *FileInfo) ModTime() time.Time { 715 return f.entry.ModificationTime 716 } 717 718 func (f *FileInfo) IsRoot() bool { 719 return f.fid == nil 720 } 721 722 func (f *FileInfo) IsDir() bool { 723 return f.entry.ICBTag.FileType == fileTypeDirectory 724 } 725 726 func (f *FileInfo) Uid() uint32 { 727 return f.entry.Uid 728 } 729 730 func (f *FileInfo) Gid() uint32 { 731 return f.entry.Gid 732 } 733 734 func (f *FileInfo) Sys() any { 735 return f 736 }