]> git.r.bdr.sh - rbdr/mobius/blobdiff - hotline/flattened_file_object.go
Account for the root
[rbdr/mobius] / hotline / flattened_file_object.go
index dfa86e091a06fc2fc73f6973b3362e0678ad9439..99ce204569551931a296db469da803799cf75be3 100644 (file)
@@ -13,6 +13,8 @@ type flattenedFileObject struct {
        FlatFileInformationFork       FlatFileInformationFork
        FlatFileDataForkHeader        FlatFileForkHeader
        FlatFileResForkHeader         FlatFileForkHeader
+
+       readOffset int // Internal offset to track read progress
 }
 
 // FlatFileHeader is the first section of a "Flattened File Object".  All fields have static values.
@@ -24,57 +26,55 @@ type FlatFileHeader struct {
 }
 
 type FlatFileInformationFork struct {
-       Platform         []byte // Operating System used. ("AMAC" or "MWIN")
-       TypeSignature    []byte // File type signature
-       CreatorSignature []byte // File creator signature
-       Flags            []byte
-       PlatformFlags    []byte
-       RSVD             []byte
-       CreateDate       []byte
-       ModifyDate       []byte
-       NameScript       []byte
-       NameSize         []byte // Length of file name (Maximum 128 characters)
-       Name             []byte // File name
-       CommentSize      []byte // Length of the comment
-       Comment          []byte // File comment
+       Platform         [4]byte // Operating System used. ("AMAC" or "MWIN")
+       TypeSignature    [4]byte // File type signature
+       CreatorSignature [4]byte // File creator signature
+       Flags            [4]byte
+       PlatformFlags    [4]byte
+       RSVD             [32]byte
+       CreateDate       [8]byte
+       ModifyDate       [8]byte
+       NameScript       [2]byte
+       NameSize         [2]byte // Length of file name (Maximum 128 characters)
+       Name             []byte  // File name
+       CommentSize      [2]byte // Length of the comment
+       Comment          []byte  // File comment
+
+       readOffset int // Internal offset to track read progress
 }
 
-func NewFlatFileInformationFork(fileName string, modifyTime []byte, typeSignature string, creatorSignature string) FlatFileInformationFork {
+func NewFlatFileInformationFork(fileName string, modifyTime [8]byte, typeSignature string, creatorSignature string) FlatFileInformationFork {
        return FlatFileInformationFork{
-               Platform:         []byte("AMAC"),           // TODO: Remove hardcode to support "AWIN" Platform (maybe?)
-               TypeSignature:    []byte(typeSignature),    // TODO: Don't infer types from filename
-               CreatorSignature: []byte(creatorSignature), // TODO: Don't infer types from filename
-               Flags:            []byte{0, 0, 0, 0},       // TODO: What is this?
-               PlatformFlags:    []byte{0, 0, 1, 0},       // TODO: What is this?
-               RSVD:             make([]byte, 32),         // Unimplemented in Hotline Protocol
-               CreateDate:       modifyTime,               // some filesystems don't support createTime
+               Platform:         [4]byte{0x41, 0x4D, 0x41, 0x43},   // "AMAC" TODO: Remove hardcode to support "AWIN" Platform (maybe?)
+               TypeSignature:    [4]byte([]byte(typeSignature)),    // TODO: Don't infer types from filename
+               CreatorSignature: [4]byte([]byte(creatorSignature)), // TODO: Don't infer types from filename
+               PlatformFlags:    [4]byte{0, 0, 1, 0},               // TODO: What is this?
+               CreateDate:       modifyTime,                        // some filesystems don't support createTime
                ModifyDate:       modifyTime,
-               NameScript:       make([]byte, 2), // TODO: What is this?
                Name:             []byte(fileName),
-               CommentSize:      []byte{0, 0},
                Comment:          []byte{}, // TODO: implement (maybe?)
        }
 }
 
-func (ffif *FlatFileInformationFork) friendlyType() []byte {
-       if name, ok := friendlyCreatorNames[string(ffif.TypeSignature)]; ok {
+func (ffif *FlatFileInformationFork) FriendlyType() []byte {
+       if name, ok := friendlyCreatorNames[string(ffif.TypeSignature[:])]; ok {
                return []byte(name)
        }
-       return ffif.TypeSignature
+       return ffif.TypeSignature[:]
 }
 
-func (ffif *FlatFileInformationFork) friendlyCreator() []byte {
-       if name, ok := friendlyCreatorNames[string(ffif.CreatorSignature)]; ok {
+func (ffif *FlatFileInformationFork) FriendlyCreator() []byte {
+       if name, ok := friendlyCreatorNames[string(ffif.CreatorSignature[:])]; ok {
                return []byte(name)
        }
-       return ffif.CreatorSignature
+       return ffif.CreatorSignature[:]
 }
 
-func (ffif *FlatFileInformationFork) setComment(comment []byte) error {
-       ffif.CommentSize = make([]byte, 2)
+func (ffif *FlatFileInformationFork) SetComment(comment []byte) error {
+       commentSize := make([]byte, 2)
        ffif.Comment = comment
-       binary.BigEndian.PutUint16(ffif.CommentSize, uint16(len(comment)))
-
+       binary.BigEndian.PutUint16(commentSize, uint16(len(comment)))
+       ffif.CommentSize = [2]byte(commentSize)
        // TODO: return err if comment is too long
        return nil
 }
@@ -102,8 +102,10 @@ func (ffif *FlatFileInformationFork) Size() [4]byte {
 }
 
 func (ffo *flattenedFileObject) TransferSize(offset int64) []byte {
+       ffoCopy := *ffo
+
        // get length of the flattenedFileObject, including the info fork
-       b, _ := io.ReadAll(ffo)
+       b, _ := io.ReadAll(&ffoCopy)
        payloadSize := len(b)
 
        // length of data fork
@@ -133,56 +135,62 @@ type FlatFileForkHeader struct {
 }
 
 func (ffif *FlatFileInformationFork) Read(p []byte) (int, error) {
-       return copy(p,
-               slices.Concat(
-                       ffif.Platform,
-                       ffif.TypeSignature,
-                       ffif.CreatorSignature,
-                       ffif.Flags,
-                       ffif.PlatformFlags,
-                       ffif.RSVD,
-                       ffif.CreateDate,
-                       ffif.ModifyDate,
-                       ffif.NameScript,
-                       ffif.ReadNameSize(),
-                       ffif.Name,
-                       ffif.CommentSize,
-                       ffif.Comment,
-               ),
-       ), io.EOF
+       buf := slices.Concat(
+               ffif.Platform[:],
+               ffif.TypeSignature[:],
+               ffif.CreatorSignature[:],
+               ffif.Flags[:],
+               ffif.PlatformFlags[:],
+               ffif.RSVD[:],
+               ffif.CreateDate[:],
+               ffif.ModifyDate[:],
+               ffif.NameScript[:],
+               ffif.ReadNameSize(),
+               ffif.Name,
+               ffif.CommentSize[:],
+               ffif.Comment,
+       )
+
+       if ffif.readOffset >= len(buf) {
+               return 0, io.EOF // All bytes have been read
+       }
+
+       n := copy(p, buf[ffif.readOffset:])
+       ffif.readOffset += n
+
+       return n, nil
 }
 
-// Write implements the io.Writeer interface for FlatFileInformationFork
+// Write implements the io.Writer interface for FlatFileInformationFork
 func (ffif *FlatFileInformationFork) Write(p []byte) (int, error) {
        nameSize := p[70:72]
        bs := binary.BigEndian.Uint16(nameSize)
        total := 72 + bs
 
-       ffif.Platform = p[0:4]
-       ffif.TypeSignature = p[4:8]
-       ffif.CreatorSignature = p[8:12]
-       ffif.Flags = p[12:16]
-       ffif.PlatformFlags = p[16:20]
-       ffif.RSVD = p[20:52]
-       ffif.CreateDate = p[52:60]
-       ffif.ModifyDate = p[60:68]
-       ffif.NameScript = p[68:70]
-       ffif.NameSize = p[70:72]
+       ffif.Platform = [4]byte(p[0:4])
+       ffif.TypeSignature = [4]byte(p[4:8])
+       ffif.CreatorSignature = [4]byte(p[8:12])
+       ffif.Flags = [4]byte(p[12:16])
+       ffif.PlatformFlags = [4]byte(p[16:20])
+       ffif.RSVD = [32]byte(p[20:52])
+       ffif.CreateDate = [8]byte(p[52:60])
+       ffif.ModifyDate = [8]byte(p[60:68])
+       ffif.NameScript = [2]byte(p[68:70])
+       ffif.NameSize = [2]byte(p[70:72])
        ffif.Name = p[72:total]
 
        if len(p) > int(total) {
-               ffif.CommentSize = p[total : total+2]
-               commentLen := binary.BigEndian.Uint16(ffif.CommentSize)
-
+               ffif.CommentSize = [2]byte(p[total : total+2])
+               commentLen := binary.BigEndian.Uint16(ffif.CommentSize[:])
                commentStartPos := int(total) + 2
                commentEndPos := int(total) + 2 + int(commentLen)
 
                ffif.Comment = p[commentStartPos:commentEndPos]
 
-               total = uint16(commentEndPos)
+               //total = uint16(commentEndPos)
        }
 
-       return int(total), nil
+       return len(p), nil
 }
 
 func (ffif *FlatFileInformationFork) UnmarshalBinary(b []byte) error {
@@ -190,21 +198,21 @@ func (ffif *FlatFileInformationFork) UnmarshalBinary(b []byte) error {
        bs := binary.BigEndian.Uint16(nameSize)
        nameEnd := 72 + bs
 
-       ffif.Platform = b[0:4]
-       ffif.TypeSignature = b[4:8]
-       ffif.CreatorSignature = b[8:12]
-       ffif.Flags = b[12:16]
-       ffif.PlatformFlags = b[16:20]
-       ffif.RSVD = b[20:52]
-       ffif.CreateDate = b[52:60]
-       ffif.ModifyDate = b[60:68]
-       ffif.NameScript = b[68:70]
-       ffif.NameSize = b[70:72]
+       ffif.Platform = [4]byte(b[0:4])
+       ffif.TypeSignature = [4]byte(b[4:8])
+       ffif.CreatorSignature = [4]byte(b[8:12])
+       ffif.Flags = [4]byte(b[12:16])
+       ffif.PlatformFlags = [4]byte(b[16:20])
+       ffif.RSVD = [32]byte(b[20:52])
+       ffif.CreateDate = [8]byte(b[52:60])
+       ffif.ModifyDate = [8]byte(b[60:68])
+       ffif.NameScript = [2]byte(b[68:70])
+       ffif.NameSize = [2]byte(b[70:72])
        ffif.Name = b[72:nameEnd]
 
        if len(b) > int(nameEnd) {
-               ffif.CommentSize = b[nameEnd : nameEnd+2]
-               commentLen := binary.BigEndian.Uint16(ffif.CommentSize)
+               ffif.CommentSize = [2]byte(b[nameEnd : nameEnd+2])
+               commentLen := binary.BigEndian.Uint16(ffif.CommentSize[:])
 
                commentStartPos := int(nameEnd) + 2
                commentEndPos := int(nameEnd) + 2 + int(commentLen)
@@ -217,7 +225,7 @@ func (ffif *FlatFileInformationFork) UnmarshalBinary(b []byte) error {
 
 // Read implements the io.Reader interface for flattenedFileObject
 func (ffo *flattenedFileObject) Read(p []byte) (int, error) {
-       return copy(p, slices.Concat(
+       buf := slices.Concat(
                ffo.FlatFileHeader.Format[:],
                ffo.FlatFileHeader.Version[:],
                ffo.FlatFileHeader.RSVD[:],
@@ -226,25 +234,33 @@ func (ffo *flattenedFileObject) Read(p []byte) (int, error) {
                []byte{0, 0, 0, 0},
                make([]byte, 4),
                ffo.FlatFileInformationFork.DataSize(),
-               ffo.FlatFileInformationFork.Platform,
-               ffo.FlatFileInformationFork.TypeSignature,
-               ffo.FlatFileInformationFork.CreatorSignature,
-               ffo.FlatFileInformationFork.Flags,
-               ffo.FlatFileInformationFork.PlatformFlags,
-               ffo.FlatFileInformationFork.RSVD,
-               ffo.FlatFileInformationFork.CreateDate,
-               ffo.FlatFileInformationFork.ModifyDate,
-               ffo.FlatFileInformationFork.NameScript,
+               ffo.FlatFileInformationFork.Platform[:],
+               ffo.FlatFileInformationFork.TypeSignature[:],
+               ffo.FlatFileInformationFork.CreatorSignature[:],
+               ffo.FlatFileInformationFork.Flags[:],
+               ffo.FlatFileInformationFork.PlatformFlags[:],
+               ffo.FlatFileInformationFork.RSVD[:],
+               ffo.FlatFileInformationFork.CreateDate[:],
+               ffo.FlatFileInformationFork.ModifyDate[:],
+               ffo.FlatFileInformationFork.NameScript[:],
                ffo.FlatFileInformationFork.ReadNameSize(),
                ffo.FlatFileInformationFork.Name,
-               ffo.FlatFileInformationFork.CommentSize,
+               ffo.FlatFileInformationFork.CommentSize[:],
                ffo.FlatFileInformationFork.Comment,
                ffo.FlatFileDataForkHeader.ForkType[:],
                ffo.FlatFileDataForkHeader.CompressionType[:],
                ffo.FlatFileDataForkHeader.RSVD[:],
                ffo.FlatFileDataForkHeader.DataSize[:],
-       ),
-       ), io.EOF
+       )
+
+       if ffo.readOffset >= len(buf) {
+               return 0, io.EOF // All bytes have been read
+       }
+
+       n := copy(p, buf[ffo.readOffset:])
+       ffo.readOffset += n
+
+       return n, nil
 }
 
 func (ffo *flattenedFileObject) ReadFrom(r io.Reader) (int64, error) {