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  }