From 8738df5358f31f0f657719f591deb08e4a89a208 Mon Sep 17 00:00:00 2001 From: konoui Date: Wed, 15 May 2024 21:08:57 +0900 Subject: [PATCH] refactor --- pkg/lipo/archs.go | 27 ++++++++++++++++++--------- pkg/lipo/detailed_info.go | 7 +++---- pkg/lipo/info.go | 24 +++++++++--------------- pkg/lipo/operation.go | 39 +++++++++++++++++---------------------- pkg/lmacho/fat.go | 10 +++++----- pkg/lmacho/reader.go | 2 +- pkg/lmacho/reader_test.go | 2 +- pkg/lmacho/writer.go | 32 ++++++++++++-------------------- 8 files changed, 66 insertions(+), 77 deletions(-) diff --git a/pkg/lipo/archs.go b/pkg/lipo/archs.go index a478f4a..7e44e1f 100644 --- a/pkg/lipo/archs.go +++ b/pkg/lipo/archs.go @@ -10,24 +10,33 @@ func (l *Lipo) Archs() ([]string, error) { } bin := l.in[0] - return archs(bin) + cpus, _, err := archs(bin) + return cpus, err } -func archs(bin string) ([]string, error) { - obj, typ, err := inspect(bin) +func archs(bin string) ([]string, inspectType, error) { + typ, err := inspect(bin) if err != nil { - return nil, err + return nil, inspectUnknown, err } switch typ { case inspectThin: - fallthrough + objs, err := OpenArches([]*ArchInput{{Bin: bin}}) + if err != nil { + return nil, typ, err + } + return []string{objs[0].CPUString()}, inspectThin, nil case inspectArchive: - return []string{obj.CPUString()}, nil + objs, err := OpenArchiveArches(bin) + if err != nil { + return nil, typ, err + } + return []string{objs[0].CPUString()}, typ, nil case inspectFat: fat, err := OpenFatFile(bin) if err != nil { - return nil, fmt.Errorf("internal error: %w", err) + return nil, typ, fmt.Errorf("internal error: %w", err) } defer fat.Close() @@ -35,8 +44,8 @@ func archs(bin string) ([]string, error) { for i := range cpus { cpus[i] = fat.Arches[i].CPUString() } - return cpus, nil + return cpus, typ, nil default: - return nil, fmt.Errorf("unexpected type: %d", typ) + return nil, inspectUnknown, fmt.Errorf("unexpected type: %d", typ) } } diff --git a/pkg/lipo/detailed_info.go b/pkg/lipo/detailed_info.go index a7a874c..3bb94d1 100644 --- a/pkg/lipo/detailed_info.go +++ b/pkg/lipo/detailed_info.go @@ -77,7 +77,7 @@ type tplFatBinary struct { func detailedInfo(bin string) (string, bool, error) { var out strings.Builder - _, typ, err := inspect(bin) + typ, err := inspect(bin) if err != nil { return "", false, err } @@ -133,13 +133,12 @@ func detailedInfo(bin string) (string, bool, error) { func tplArch(a *lmacho.FatArch) *tplFatArch { c, s := lmacho.ToCpuValues(a.CPU(), a.SubCPU()) - arch := lmacho.ToCpuString(a.CPU(), a.SubCPU()) return &tplFatArch{ - Arch: arch, + Arch: a.CPUString(), CpuType: c, SubCpuType: s, Capabilities: fmt.Sprintf("0x%x", (a.SubCPU()&lmacho.MaskSubCpuType)>>24), - Offset: a.FatArchHeader().Offset, + Offset: a.Offset(), Size: a.Size(), AlignBit: a.Align(), Align: 1 << a.Align(), diff --git a/pkg/lipo/info.go b/pkg/lipo/info.go index 28de77e..cafe9cf 100644 --- a/pkg/lipo/info.go +++ b/pkg/lipo/info.go @@ -13,11 +13,11 @@ func (l *Lipo) Info() ([]string, error) { fat := make([]string, 0, len(l.in)) thin := make([]string, 0, len(l.in)) for _, bin := range l.in { - v, isFat, err := info(bin) + v, typ, err := info(bin) if err != nil { return nil, err } - if isFat { + if typ == inspectFat { fat = append(fat, v) } else { thin = append(thin, v) @@ -27,29 +27,23 @@ func (l *Lipo) Info() ([]string, error) { return append(fat, thin...), nil } -func info(bin string) (string, bool, error) { +func info(bin string) (string, inspectType, error) { fatFmt := "Architectures in the fat file: %s are: %s" - arches, err := archs(bin) + arches, typ, err := archs(bin) if err != nil { - return "", false, err + return "", inspectUnknown, err } v := strings.Join(arches, " ") - - _, typ, err := inspect(bin) - if err != nil { - return "", false, err - } - switch typ { case inspectThin: - fallthrough + return fmt.Sprintf("Non-fat file: %s is architecture: %s", bin, v), inspectThin, nil case inspectArchive: - return fmt.Sprintf("Non-fat file: %s is architecture: %s", bin, v), false, nil + return fmt.Sprintf("Non-fat file: %s is architecture: %s", bin, v), inspectArchive, nil case inspectFat: - return fmt.Sprintf(fatFmt, bin, v), true, nil + return fmt.Sprintf(fatFmt, bin, v), inspectFat, nil default: - return "", false, fmt.Errorf("unexpected type: %d", typ) + return "", inspectUnknown, fmt.Errorf("unexpected type: %d", typ) } } diff --git a/pkg/lipo/operation.go b/pkg/lipo/operation.go index 340e9e9..0948466 100644 --- a/pkg/lipo/operation.go +++ b/pkg/lipo/operation.go @@ -1,6 +1,7 @@ package lipo import ( + "bytes" "errors" "fmt" "math" @@ -8,6 +9,7 @@ import ( "strconv" "strings" + "github.com/konoui/lipo/pkg/ar" "github.com/konoui/lipo/pkg/lmacho" "github.com/konoui/lipo/pkg/util" ) @@ -120,43 +122,36 @@ const ( inspectUnknown ) -// inspect return object if the file is ar or macho(thin) object -func inspect(p string) (Arch, inspectType, error) { - // handle general errors +func inspect(p string) (inspectType, error) { f, err := os.Open(p) if err != nil { - return nil, inspectUnknown, err + return inspectUnknown, err } defer f.Close() + baseErr := fmt.Errorf("can't figure out the architecture type of: %s", p) inspectedErrs := []error{} - ff, err := OpenFatFile(p) - if err == nil { - defer ff.Close() - return nil, inspectFat, nil + + buf := make([]byte, 40) + if _, err := f.Read(buf); err != nil { + return inspectUnknown, errors.Join(baseErr, errors.New("cannot read first 40 bytes")) } + _, err = lmacho.NewFatReader(bytes.NewReader(buf)) + if err == nil { + return inspectFat, nil + } if errors.Is(err, lmacho.ErrThin) { - a, err := OpenArches([]*ArchInput{{Bin: p}}) - if err != nil { - return nil, inspectUnknown, err // unexpected error - } - defer close(a...) - return a[0], inspectThin, nil + return inspectThin, nil } inspectedErrs = append(inspectedErrs, err) - objs, err := OpenArchiveArches(p) + _, err = ar.NewReader(bytes.NewReader(buf)) if err == nil { - defer close(objs...) - return objs[0], inspectArchive, nil - } - if strings.HasPrefix(err.Error(), "archive member") { - return nil, inspectUnknown, err + return inspectArchive, nil } inspectedErrs = append(inspectedErrs, err) - - return nil, inspectUnknown, errors.Join(fmt.Errorf("can't figure out the architecture type of: %s", p), errors.Join(inspectedErrs...)) + return inspectUnknown, errors.Join(baseErr, errors.Join(inspectedErrs...)) } diff --git a/pkg/lmacho/fat.go b/pkg/lmacho/fat.go index db16df5..72eeb42 100644 --- a/pkg/lmacho/fat.go +++ b/pkg/lmacho/fat.go @@ -70,6 +70,10 @@ func (fa *FatArch) Type() macho.Type { return fa.typ } +func (fa *FatArch) Offset() uint64 { + return fa.faHdr.Offset +} + func (fa *FatArch) CPUString() string { return ToCpuString(fa.CPU(), fa.SubCPU()) } @@ -86,10 +90,6 @@ func (fa *FatArch) Seek(offset int64, whence int) (int64, error) { return fa.sr.Seek(offset, whence) } -func (fa *FatArch) FatArchHeader() FatArchHeader { - return fa.faHdr -} - // Arch presents an object of thin file type Arch struct { cpu Cpu @@ -150,7 +150,7 @@ type FatFile struct { // NewFatFile is wrapper for Fat Reader func NewFatFile(ra io.ReaderAt) (*FatFile, error) { - r, err := NewReader(ra) + r, err := NewFatReader(ra) if err != nil { return nil, err } diff --git a/pkg/lmacho/reader.go b/pkg/lmacho/reader.go index 00a7c40..67e8ca7 100644 --- a/pkg/lmacho/reader.go +++ b/pkg/lmacho/reader.go @@ -15,7 +15,7 @@ type Reader struct { nextNArch uint32 } -func NewReader(r io.ReaderAt) (*Reader, error) { +func NewFatReader(r io.ReaderAt) (*Reader, error) { sr := io.NewSectionReader(r, 0, 1<<63-1) var ff FatHeader diff --git a/pkg/lmacho/reader_test.go b/pkg/lmacho/reader_test.go index c5db4d1..8baa94b 100644 --- a/pkg/lmacho/reader_test.go +++ b/pkg/lmacho/reader_test.go @@ -71,7 +71,7 @@ func TestNewReader(t *testing.T) { } defer f.Close() - reader, err := lmacho.NewReader(f) + reader, err := lmacho.NewFatReader(f) if err != nil { t.Errorf("NewReader() error = %v", err) return diff --git a/pkg/lmacho/writer.go b/pkg/lmacho/writer.go index cb984ec..914434f 100644 --- a/pkg/lmacho/writer.go +++ b/pkg/lmacho/writer.go @@ -13,11 +13,6 @@ func Create[T Object](w io.Writer, objects []T, fat64 bool, hideARM64 bool) erro return errors.New("file contains no images") } - newobjects := make([]Object, len(objects)) - for i := range newobjects { - newobjects[i] = objects[i] - } - if err := validateHideARM64Objects(objects, hideARM64); err != nil { return err } @@ -27,7 +22,7 @@ func Create[T Object](w io.Writer, objects []T, fat64 bool, hideARM64 bool) erro magic = MagicFat64 } - fatArches := newFatArches(newobjects) + fatArches := newFatArches(objects) hdr := makeFatHeader(fatArches, magic, hideARM64) if err := sortAndUpdateArches(fatArches, hdr.Magic); err != nil { return err @@ -44,22 +39,19 @@ func Create[T Object](w io.Writer, objects []T, fat64 bool, hideARM64 bool) erro return nil } -func newFatArches(objects []Object) []*FatArch { +func newFatArches[T Object](objects []T) []*FatArch { arches := make([]*FatArch, len(objects)) for i, obj := range objects { - fa, ok := obj.(*FatArch) - if !ok { - fa = &FatArch{ - sr: io.NewSectionReader(obj, 0, int64(obj.Size())), - typ: obj.Type(), - faHdr: FatArchHeader{ - Cpu: obj.CPU(), - SubCpu: obj.SubCPU(), - Size: obj.Size(), - Offset: 0, // will be filled - Align: obj.Align(), - }, - } + fa := &FatArch{ + sr: io.NewSectionReader(obj, 0, int64(obj.Size())), + typ: obj.Type(), + faHdr: FatArchHeader{ + Cpu: obj.CPU(), + SubCpu: obj.SubCPU(), + Size: obj.Size(), + Offset: 0, // will be filled + Align: obj.Align(), + }, } arches[i] = fa }