github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/fatbin/create.go (about)

     1  // Copyright 2019 GRAIL, Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache 2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  package fatbin
     6  
     7  import (
     8  	"archive/zip"
     9  	"io"
    10  	"os"
    11  )
    12  
    13  // Writer is used to append fatbin images to an existing binary.
    14  type Writer struct {
    15  	z            *zip.Writer
    16  	w            io.Writer
    17  	off          int64
    18  	goos, goarch string
    19  }
    20  
    21  // NewFileWriter returns a writer that can be used to append fatbin
    22  // images to the binary represented by the provided file.
    23  // NewFileWriter removes any existing fatbin images that may be
    24  // attached to the binary. It relies on content sniffing (see Sniff)
    25  // to determine its offset.
    26  func NewFileWriter(file *os.File) (*Writer, error) {
    27  	info, err := file.Stat()
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	goos, goarch, offset, err := Sniff(file, info.Size())
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	if err := file.Truncate(offset); err != nil {
    36  		return nil, err
    37  	}
    38  	_, err = file.Seek(0, io.SeekEnd)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	return NewWriter(file, offset, goos, goarch), nil
    43  }
    44  
    45  // NewWriter returns a writer that may be used to append fatbin
    46  // images to the writer w. The writer should be positioned at the end
    47  // of the base binary image.
    48  func NewWriter(w io.Writer, offset int64, goos, goarch string) *Writer {
    49  	return &Writer{z: zip.NewWriter(w), w: w, off: offset, goos: goos, goarch: goarch}
    50  }
    51  
    52  // Create returns a Writer into which the image for the provided goos
    53  // and goarch should be written. The image's contents must be written
    54  // before the next call to Create or Close.
    55  func (w *Writer) Create(goos, goarch string) (io.Writer, error) {
    56  	return w.z.Create(goos + "/" + goarch)
    57  }
    58  
    59  // Flush flushes the unwritten data to the underlying file.
    60  func (w *Writer) Flush() error {
    61  	return w.z.Flush()
    62  }
    63  
    64  // Close should be called after all images have been written. No more
    65  // images can be written after a call to Close.
    66  func (w *Writer) Close() error {
    67  	if err := w.z.SetComment(w.goos + "/" + w.goarch); err != nil {
    68  		return err
    69  	}
    70  	if err := w.z.Close(); err != nil {
    71  		return err
    72  	}
    73  	_, err := writeFooter(w.w, w.off)
    74  	return err
    75  }