package data import ( "bytes" "compress/flate" "encoding/binary" "encoding/json" "fmt" "io" "os" ) type File struct { Size int64 `json:"size"` ZSize int64 `json:"zsize"` Offset int64 `json:"offset"` } func (f *File) Read(pf *os.File, b []byte) (int, error) { if f.ZSize > 0 { compressed := make([]byte, f.ZSize) _, err := pf.ReadAt(compressed, f.Offset) if err != nil { return 0, err } // Decompress reader := flate.NewReader(bytes.NewReader(compressed)) defer reader.Close() n, err := reader.Read(b) if err != nil && err != io.EOF { fmt.Println("Error reading file:", err, n, compressed) return 0, err } return n, nil } return pf.ReadAt(b, f.Offset) } type FileSystem struct { Files map[string]File `json:"files"` fp *os.File } func (fs *FileSystem) ToJSON() (string, error) { data, err := json.Marshal(fs) if err != nil { return "", fmt.Errorf("failed to marshal FileSystem to JSON: %v", err) } return string(data), nil } func FromJSON(jsonStr string) (*FileSystem, error) { var fs FileSystem err := json.Unmarshal([]byte(jsonStr), &fs) if err != nil { return nil, fmt.Errorf("failed to unmarshal JSON to FileSystem: %v", err) } return &fs, nil } func (fs *FileSystem) AddFile(name string, size int64, offset int64) { if fs.Files == nil { fs.Files = make(map[string]File) } fs.Files[name] = File{Size: size, Offset: offset} } func (fs *FileSystem) GetFile(name string) (File, bool) { file, exists := fs.Files[name] return file, exists } func (fs *FileSystem) ListFiles() []string { keys := make([]string, 0, len(fs.Files)) for k := range fs.Files { keys = append(keys, k) } return keys } func (fs *FileSystem) ReadFile(name string) ([]byte, int, error) { err := fs.openContainerFile() if err != nil { return []byte{}, 0, fmt.Errorf("failed to open container file: %v", err) } file, exists := fs.GetFile(name) if !exists { return []byte{}, 0, fmt.Errorf("file %s not found", name) } b := make([]byte, file.Size) len, err := file.Read(fs.fp, b) return b, len, err } func (fs *FileSystem) openContainerFile() error { if fs.fp != nil { return nil } exePath, err := os.Executable() if err != nil { return fmt.Errorf("failed to get executable path: %v", err) } fp, err := os.Open(exePath) if err != nil { return fmt.Errorf("failed to open executable file: %v", err) } fs.fp = fp return nil } func (fs *FileSystem) Close() error { if fs.fp != nil { err := fs.fp.Close() fs.fp = nil return err } return nil } func GetFileSystem() (*FileSystem, error) { exePath, err := os.Executable() if err != nil { return nil, fmt.Errorf("failed to get executable path: %v", err) } fp, err := os.Open(exePath) if err != nil { return nil, fmt.Errorf("failed to open executable file: %v", err) } defer fp.Close() // Seek to the end to find the JSON metadata stat, err := fp.Stat() if err != nil { return nil, fmt.Errorf("failed to stat executable file: %v", err) } size := stat.Size() if size < 8 { return nil, fmt.Errorf("executable file is too small to contain metadata") } _, err = fp.Seek(-8, io.SeekEnd) if err != nil { return nil, fmt.Errorf("failed to seek to end of executable file: %v", err) } var fsSize uint64 err = binary.Read(fp, binary.LittleEndian, &fsSize) if err != nil { return nil, fmt.Errorf("failed to decode metadata size: %v", err) } fmt.Println("fsSize:", fsSize) if fsSize == 0 || fsSize > uint64(size-8) { return nil, fmt.Errorf("invalid metadata size: %d", fsSize) } _, err = fp.Seek(-(8 + int64(fsSize)), io.SeekEnd) if err != nil { return nil, fmt.Errorf("failed to seek to metadata position: %v", err) } jsonData := make([]byte, fsSize) _, err = fp.Read(jsonData) if err != nil { return nil, fmt.Errorf("failed to read metadata: %v", err) } var fs FileSystem err = json.Unmarshal(jsonData, &fs) if err != nil { return nil, fmt.Errorf("failed to decode JSON metadata: %v", err) } return &fs, nil }