The Unix ar archive library for Go
This library provides a reader and a writer for Unix ar archives. The API
heavily inspired by the tar module from Go's standard library. The following
features set the library apart from other Go ar libraries such as
github.com/blakesmith/ar:
- Automatic file size determination: Add files without knowing their size
beforehand. This is useful when compressing the files on the fly while writing
them to
ararchive by stacking multipleio.Writer. - Support for long file names: The traditional
arformat has a file name size limit of 16 characters. Multiple extensions have been created to work around this.io.Writerwrites long archive names in BSD style andio.Readersupports BSD and System V/Gnu style. - Robust
io.Reader/io.WriterAPIs: Files can be writting in multipleWritecalls and they can be read in multipleReadcalls.
The ar Reader can read traditional, BSD-style and System V/Gnu-style archives.
Symbol lookup tables are currently not supported.
arReader, err := ar.NewReader(file)
if err != nil {
return err
}
// read file header and setup reader to provide the file content
header, err := arReader.Next()
if err != nil {
return err
}
// read the file content that belongs to the header that was returned by the
// previous Next() call (io.ReadAll calls arReader.Read)
content, err := io.ReadAll(arReader)
if err != nil {
return err
}The ar writer supports automatic file size determination. Consider the
following example, where a file is gzip compressed on the fly. Since the final
size of the compressed file is not known until after it is written, the Size
field of the ar header is set to ar.UnknownSize to enable automatic file
size determination.
arWriter := NewWriter(file)
// write a file header for the compressed data while signaling that the file
// size needs to be automatically determined using the UnknownSize constant
err := arWriter.WriteHeader(&Header{
Name: "data.gz",
ModTime: time.Now(),
Mode: 0o644,
Size: UnknownSize,
})
if err != nil {
panic(err)
}
// write compressed data
gzipWriter := gzip.NewWriter(arWriter)
_, err = io.Copy(gzipWriter, largeFile)
if err != nil {
return err
}
err = gzipWriter.Close()
if err != nil {
return err
}
err = arWriter.Close()
if err != nil {
return err
}When adding actual files to the ar archive, the header can be easily populated
using the helper functions NewHeaderFromFile and NewHeaderFromFileInfo.
- If the underlying
io.Writeris an*os.Fileor if it at least implementsio.WriterAtandio.Seek, automatic file size determination has a negligible performance impact. - If the underlying
io.Writeris not an*os.Fileand if it does not implementWriteAtandio.Seek, the header and file content will be buffered in memory until the nextarentry is started orCloseis called if automatic file size determination is enabled.
If a file name has more than 16 characters, it will be written in BSD-style
which can also be read by the Gnu/binutils ar tool.