all repos — homestead @ f0db45107699eb1294f6d64cbf2ddd48783f7cc0

Code for my website

fetcher: support fetching archives

Alan Pearce
commit

f0db45107699eb1294f6d64cbf2ddd48783f7cc0

parent

c4502da96d8899b770a621ce07b0a636a84f6f53

1 file changed, 68 insertions(+), 0 deletions(-)

changed files
A domain/content/fetcher/tar.go
@@ -0,0 +1,68 @@
+package fetcher + +import ( + "archive/tar" + "compress/bzip2" + "io" + "os" + + "alin.ovh/x/log" + "github.com/Southclaws/fault" + "github.com/Southclaws/fault/fmsg" +) + +func bunzip(r io.Reader) io.Reader { + return bzip2.NewReader(r) +} + +func extract(body io.Reader, root *os.Root, log *log.Logger) error { + tr := tar.NewReader(body) + for { + head, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return fault.Wrap(err, fmsg.With("could not read tar header")) + } + + log.Debug("extracting file", "name", head.Name) + + switch head.Typeflag { + case tar.TypeReg: + err := writeFile(tr, head, root) + if err != nil { + return fault.Wrap(err, fmsg.Withf("could not write file %s", head.Name)) + } + case tar.TypeDir: + err := root.MkdirAll(head.Name, head.FileInfo().Mode().Perm()) + if err != nil { + return fault.Wrap(err, fmsg.Withf("could not create directory %s", head.Name)) + } + default: + return fault.Newf("unsupported file type %d", head.Typeflag) + } + } + + return nil +} + +func writeFile(tr *tar.Reader, head *tar.Header, root *os.Root) error { + file, err := root.OpenFile(head.Name, os.O_CREATE|os.O_WRONLY, head.FileInfo().Mode().Perm()) + if err != nil { + return fault.Wrap(err, fmsg.Withf("could not open file %s", head.Name)) + } + defer file.Close() + + _, err = io.Copy(file, tr) + if err != nil { + return fault.Wrap(err, fmsg.Withf("could not write file %s", head.Name)) + } + + err = file.Sync() + if err != nil { + return fault.Wrap(err, fmsg.Withf("could not sync file %s", head.Name)) + } + + return nil +}