X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/blobdiff_plain/22c599abc18895f73e96095f35b71cf3357d41b4..4eae11a5698d60bc51d608713088c546cff3c1ba:/hotline/flattened_file_object.go diff --git a/hotline/flattened_file_object.go b/hotline/flattened_file_object.go index dfdd8a8..2cafbc9 100644 --- a/hotline/flattened_file_object.go +++ b/hotline/flattened_file_object.go @@ -2,7 +2,6 @@ package hotline import ( "encoding/binary" - "fmt" "os" ) @@ -16,19 +15,19 @@ type flattenedFileObject struct { // FlatFileHeader is the first section of a "Flattened File Object". All fields have static values. type FlatFileHeader struct { - Format []byte // Always "FILP" - Version []byte // Always 1 - RSVD []byte // Always empty zeros - ForkCount []byte // Always 2 + Format [4]byte // Always "FILP" + Version [2]byte // Always 1 + RSVD [16]byte // Always empty zeros + ForkCount [2]byte // Always 2 } // NewFlatFileHeader returns a FlatFileHeader struct func NewFlatFileHeader() FlatFileHeader { return FlatFileHeader{ - Format: []byte("FILP"), - Version: []byte{0, 1}, - RSVD: make([]byte, 16), - ForkCount: []byte{0, 2}, + Format: [4]byte{0x46, 0x49, 0x4c, 0x50}, // FILP + Version: [2]byte{0, 1}, + RSVD: [16]byte{}, + ForkCount: [2]byte{0, 2}, } } @@ -56,30 +55,30 @@ type FlatFileInformationFork struct { Comment []byte // File comment } -func NewFlatFileInformationFork(fileName string) FlatFileInformationFork { +func NewFlatFileInformationFork(fileName string, modifyTime []byte) FlatFileInformationFork { return FlatFileInformationFork{ - Platform: []byte("AMAC"), // TODO: Remove hardcode to support "AWIN" Platform (maybe?) - TypeSignature: []byte(fileTypeFromFilename(fileName)), // TODO: Don't infer types from filename - CreatorSignature: []byte(fileCreatorFromFilename(fileName)), // 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: []byte{0x07, 0x70, 0x00, 0x00, 0xba, 0x74, 0x24, 0x73}, // TODO: implement - ModifyDate: []byte{0x07, 0x70, 0x00, 0x00, 0xba, 0x74, 0x24, 0x73}, // TODO: implement - NameScript: make([]byte, 2), // TODO: What is this? + Platform: []byte("AMAC"), // TODO: Remove hardcode to support "AWIN" Platform (maybe?) + TypeSignature: []byte(fileTypeFromFilename(fileName).TypeCode), // TODO: Don't infer types from filename + CreatorSignature: []byte(fileTypeFromFilename(fileName).CreatorCode), // 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 + ModifyDate: modifyTime, + NameScript: make([]byte, 2), // TODO: What is this? Name: []byte(fileName), - Comment: []byte("TODO"), // TODO: implement (maybe?) + CommentSize: []byte{0, 0}, + Comment: []byte{}, // TODO: implement (maybe?) } } -// Size of the flat file information fork, which is the fixed size of 72 bytes -// plus the number of bytes in the FileName -// TODO: plus the size of the Comment! +// DataSize calculates the size of the flat file information fork, which is +// 72 bytes for the fixed length fields plus the length of the Name + Comment func (ffif FlatFileInformationFork) DataSize() []byte { size := make([]byte, 4) - nameLen := len(ffif.Name) + //TODO: Can I do math directly on two byte slices? - dataSize := nameLen + 74 + dataSize := len(ffif.Name) + len(ffif.Comment) + 74 binary.BigEndian.PutUint32(size, uint32(dataSize)) @@ -87,7 +86,7 @@ func (ffif FlatFileInformationFork) DataSize() []byte { } func (ffo flattenedFileObject) TransferSize() []byte { - payloadSize := len(ffo.Payload()) + payloadSize := len(ffo.BinaryMarshal()) dataSize := binary.BigEndian.Uint32(ffo.FlatFileDataForkHeader.DataSize) transferSize := make([]byte, 4) @@ -110,15 +109,6 @@ type FlatFileDataForkHeader struct { DataSize []byte } -func NewFlatFileDataForkHeader() FlatFileDataForkHeader { - return FlatFileDataForkHeader{ - ForkType: []byte("DATA"), - CompressionType: []byte{0, 0, 0, 0}, - RSVD: []byte{0, 0, 0, 0}, - // DataSize: []byte{0, 0, 0x03, 0xc3}, - } -} - // ReadFlattenedFileObject parses a byte slice into a flattenedFileObject func ReadFlattenedFileObject(bytes []byte) flattenedFileObject { nameSize := bytes[110:112] @@ -138,12 +128,7 @@ func ReadFlattenedFileObject(bytes []byte) flattenedFileObject { //dataSize := binary.BigEndian.Uint32(dataSizeField) ffo := flattenedFileObject{ - FlatFileHeader: FlatFileHeader{ - Format: bytes[0:4], - Version: bytes[4:6], - RSVD: bytes[6:22], - ForkCount: bytes[22:24], - }, + FlatFileHeader: NewFlatFileHeader(), FlatFileInformationForkHeader: FlatFileInformationForkHeader{ ForkType: bytes[24:28], CompressionType: bytes[28:32], @@ -176,12 +161,12 @@ func ReadFlattenedFileObject(bytes []byte) flattenedFileObject { return ffo } -func (f flattenedFileObject) Payload() []byte { +func (f flattenedFileObject) BinaryMarshal() []byte { var out []byte - out = append(out, f.FlatFileHeader.Format...) - out = append(out, f.FlatFileHeader.Version...) - out = append(out, f.FlatFileHeader.RSVD...) - out = append(out, f.FlatFileHeader.ForkCount...) + out = append(out, f.FlatFileHeader.Format[:]...) + out = append(out, f.FlatFileHeader.Version[:]...) + out = append(out, f.FlatFileHeader.RSVD[:]...) + out = append(out, f.FlatFileHeader.ForkCount[:]...) out = append(out, []byte("INFO")...) out = append(out, []byte{0, 0, 0, 0}...) @@ -199,9 +184,8 @@ func (f flattenedFileObject) Payload() []byte { out = append(out, f.FlatFileInformationFork.NameScript...) out = append(out, f.FlatFileInformationFork.ReadNameSize()...) out = append(out, f.FlatFileInformationFork.Name...) - - // TODO: Implement commentlen and comment field - out = append(out, []byte{0, 0}...) + out = append(out, f.FlatFileInformationFork.CommentSize...) + out = append(out, f.FlatFileInformationFork.Comment...) out = append(out, f.FlatFileDataForkHeader.ForkType...) out = append(out, f.FlatFileDataForkHeader.CompressionType...) @@ -211,24 +195,30 @@ func (f flattenedFileObject) Payload() []byte { return out } -func NewFlattenedFileObject(filePath string, fileName string) (flattenedFileObject, error) { - file, err := os.Open(fmt.Sprintf("%v/%v", filePath, fileName)) +func NewFlattenedFileObject(fileRoot string, filePath, fileName []byte) (*flattenedFileObject, error) { + fullFilePath, err := readPath(fileRoot, filePath, fileName) + if err != nil { + return nil, err + } + file, err := os.Open(fullFilePath) if err != nil { - return flattenedFileObject{}, err + return nil, err } - defer file.Close() + defer func(file *os.File) { _ = file.Close() }(file) fileInfo, err := file.Stat() if err != nil { - return flattenedFileObject{}, err + return nil, err } dataSize := make([]byte, 4) binary.BigEndian.PutUint32(dataSize, uint32(fileInfo.Size())) - return flattenedFileObject{ + mTime := toHotlineTime(fileInfo.ModTime()) + + return &flattenedFileObject{ FlatFileHeader: NewFlatFileHeader(), - FlatFileInformationFork: NewFlatFileInformationFork(fileName), + FlatFileInformationFork: NewFlatFileInformationFork(string(fileName), mTime), FlatFileDataForkHeader: FlatFileDataForkHeader{ ForkType: []byte("DATA"), CompressionType: []byte{0, 0, 0, 0},