package hotline
import (
+ "bytes"
"encoding/binary"
"io"
+ "slices"
)
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.
Name []byte // File name
CommentSize []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 (ffo *flattenedFileObject) TransferSize(offset int64) []byte {
// get length of the flattenedFileObject, including the info fork
- payloadSize := len(ffo.BinaryMarshal())
+ b, _ := io.ReadAll(ffo)
+ payloadSize := len(b)
// length of data fork
dataSize := binary.BigEndian.Uint32(ffo.FlatFileDataForkHeader.DataSize[:])
resForkSize := binary.BigEndian.Uint32(ffo.FlatFileResForkHeader.DataSize[:])
size := make([]byte, 4)
- binary.BigEndian.PutUint32(size[:], dataSize+resForkSize+uint32(payloadSize)-uint32(offset))
+ binary.BigEndian.PutUint32(size, dataSize+resForkSize+uint32(payloadSize)-uint32(offset))
return size
}
DataSize [4]byte
}
-func (ffif *FlatFileInformationFork) MarshalBinary() []byte {
- var b []byte
- b = append(b, ffif.Platform...)
- b = append(b, ffif.TypeSignature...)
- b = append(b, ffif.CreatorSignature...)
- b = append(b, ffif.Flags...)
- b = append(b, ffif.PlatformFlags...)
- b = append(b, ffif.RSVD...)
- b = append(b, ffif.CreateDate...)
- b = append(b, ffif.ModifyDate...)
- b = append(b, ffif.NameScript...)
- b = append(b, ffif.ReadNameSize()...)
- b = append(b, ffif.Name...)
- b = append(b, ffif.CommentSize...)
- b = append(b, ffif.Comment...)
+func (ffif *FlatFileInformationFork) Read(p []byte) (int, error) {
+ 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
+ }
- return b
+ n := copy(p, buf[ffif.readOffset:])
+ ffif.readOffset += n
+
+ return n, nil
+}
+
+// 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.Name = p[72:total]
+
+ if len(p) > int(total) {
+ ffif.CommentSize = 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)
+ }
+
+ return len(p), nil
}
func (ffif *FlatFileInformationFork) UnmarshalBinary(b []byte) error {
return nil
}
-func (ffo *flattenedFileObject) BinaryMarshal() []byte {
- var out []byte
- out = append(out, ffo.FlatFileHeader.Format[:]...)
- out = append(out, ffo.FlatFileHeader.Version[:]...)
- out = append(out, ffo.FlatFileHeader.RSVD[:]...)
- out = append(out, ffo.FlatFileHeader.ForkCount[:]...)
-
- out = append(out, []byte("INFO")...)
- out = append(out, []byte{0, 0, 0, 0}...)
- out = append(out, make([]byte, 4)...)
- out = append(out, ffo.FlatFileInformationFork.DataSize()...)
-
- out = append(out, ffo.FlatFileInformationFork.Platform...)
- out = append(out, ffo.FlatFileInformationFork.TypeSignature...)
- out = append(out, ffo.FlatFileInformationFork.CreatorSignature...)
- out = append(out, ffo.FlatFileInformationFork.Flags...)
- out = append(out, ffo.FlatFileInformationFork.PlatformFlags...)
- out = append(out, ffo.FlatFileInformationFork.RSVD...)
- out = append(out, ffo.FlatFileInformationFork.CreateDate...)
- out = append(out, ffo.FlatFileInformationFork.ModifyDate...)
- out = append(out, ffo.FlatFileInformationFork.NameScript...)
- out = append(out, ffo.FlatFileInformationFork.ReadNameSize()...)
- out = append(out, ffo.FlatFileInformationFork.Name...)
- out = append(out, ffo.FlatFileInformationFork.CommentSize...)
- out = append(out, ffo.FlatFileInformationFork.Comment...)
+// Read implements the io.Reader interface for flattenedFileObject
+func (ffo *flattenedFileObject) Read(p []byte) (int, error) {
+ buf := slices.Concat(
+ ffo.FlatFileHeader.Format[:],
+ ffo.FlatFileHeader.Version[:],
+ ffo.FlatFileHeader.RSVD[:],
+ ffo.FlatFileHeader.ForkCount[:],
+ []byte("INFO"),
+ []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.ReadNameSize(),
+ ffo.FlatFileInformationFork.Name,
+ ffo.FlatFileInformationFork.CommentSize,
+ ffo.FlatFileInformationFork.Comment,
+ ffo.FlatFileDataForkHeader.ForkType[:],
+ ffo.FlatFileDataForkHeader.CompressionType[:],
+ ffo.FlatFileDataForkHeader.RSVD[:],
+ ffo.FlatFileDataForkHeader.DataSize[:],
+ )
+
+ if ffo.readOffset >= len(buf) {
+ return 0, io.EOF // All bytes have been read
+ }
- out = append(out, ffo.FlatFileDataForkHeader.ForkType[:]...)
- out = append(out, ffo.FlatFileDataForkHeader.CompressionType[:]...)
- out = append(out, ffo.FlatFileDataForkHeader.RSVD[:]...)
- out = append(out, ffo.FlatFileDataForkHeader.DataSize[:]...)
+ n := copy(p, buf[ffo.readOffset:])
+ ffo.readOffset += n
- return out
+ return n, nil
}
-func (ffo *flattenedFileObject) ReadFrom(r io.Reader) (int, error) {
- var n int
+func (ffo *flattenedFileObject) ReadFrom(r io.Reader) (int64, error) {
+ var n int64
if err := binary.Read(r, binary.BigEndian, &ffo.FlatFileHeader); err != nil {
return n, err
return n, err
}
- if err := ffo.FlatFileInformationFork.UnmarshalBinary(ffifBuf); err != nil {
+ _, err := io.Copy(&ffo.FlatFileInformationFork, bytes.NewReader(ffifBuf))
+ if err != nil {
return n, err
}