diff options
Diffstat (limited to 'system')
-rw-r--r-- | system/admin/upload/backup.go | 91 | ||||
-rw-r--r-- | system/backup/archive.go | 95 |
2 files changed, 102 insertions, 84 deletions
diff --git a/system/admin/upload/backup.go b/system/admin/upload/backup.go index b4f6393..9dc9e31 100644 --- a/system/admin/upload/backup.go +++ b/system/admin/upload/backup.go @@ -1,8 +1,6 @@ package upload import ( - "archive/tar" - "compress/gzip" "context" "fmt" "io" @@ -10,6 +8,8 @@ import ( "os" "path/filepath" "time" + + "github.com/ponzu-cms/ponzu/system/backup" ) // Backup creates an archive of a project's uploads and writes it @@ -18,105 +18,28 @@ func Backup(ctx context.Context, res http.ResponseWriter) error { ts := time.Now().Unix() filename := fmt.Sprintf("uploads-%d.bak.tar.gz", ts) tmp := os.TempDir() - backup := filepath.Join(tmp, filename) + bk := filepath.Join(tmp, filename) // create uploads-{stamp}.bak.tar.gz - f, err := os.Create(backup) + f, err := os.Create(bk) if err != nil { return err } - // loop through directory and gzip files - // add all to uploads.bak.tar.gz tarball - gz := gzip.NewWriter(f) - tarball := tar.NewWriter(gz) - - errChan := make(chan error, 1) - walkFn := func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - hdr, err := tar.FileInfoHeader(info, "") - if err != nil { - return err - } - - hdr.Name = path - - err = tarball.WriteHeader(hdr) - if err != nil { - return err - } - - if !info.IsDir() { - src, err := os.Open(path) - if err != nil { - return err - } - defer src.Close() - - _, err = io.Copy(tarball, src) - if err != nil { - return err - } - - err = tarball.Flush() - if err != nil { - return err - } - - err = gz.Flush() - if err != nil { - return err - } - } - - return nil - } - - // stop processing if we get a cancellation signal - err = filepath.Walk("uploads", func(path string, info os.FileInfo, err error) error { - go func() { errChan <- walkFn(path, info, err) }() + err = backup.ArchiveFS(ctx, "uploads", f) - select { - case <-ctx.Done(): - if err := ctx.Err(); err != nil { - return err - } - case err := <-errChan: - if err != nil { - return err - } - } - - return nil - }) - if err != nil { - fmt.Println(err) - return err - } - - err = gz.Close() - if err != nil { - return err - } - err = tarball.Close() - if err != nil { - return err - } err = f.Close() if err != nil { return err } // write data to response - data, err := os.Open(backup) + data, err := os.Open(bk) if err != nil { return err } defer data.Close() - defer os.Remove(backup) + defer os.Remove(bk) disposition := `attachment; filename=%s` info, err := data.Stat() diff --git a/system/backup/archive.go b/system/backup/archive.go new file mode 100644 index 0000000..0a8b964 --- /dev/null +++ b/system/backup/archive.go @@ -0,0 +1,95 @@ +package backup + +import ( + "archive/tar" + "compress/gzip" + "context" + "fmt" + "io" + "os" + "path/filepath" +) + +// ArchiveFS walks the filesystem starting from basedir writing files encountered +// tarred and gzipped to the provided writer +func ArchiveFS(ctx context.Context, basedir string, w io.Writer) error { + gz := gzip.NewWriter(w) + tarball := tar.NewWriter(gz) + + errChan := make(chan error, 1) + walkFn := func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + hdr, err := tar.FileInfoHeader(info, "") + if err != nil { + return err + } + + hdr.Name = path + + err = tarball.WriteHeader(hdr) + if err != nil { + return err + } + + if !info.IsDir() { + src, err := os.Open(path) + if err != nil { + return err + } + defer src.Close() + + _, err = io.Copy(tarball, src) + if err != nil { + return err + } + + err = tarball.Flush() + if err != nil { + return err + } + + err = gz.Flush() + if err != nil { + return err + } + } + + return nil + } + + // stop processing if we get a cancellation signal + err := filepath.Walk(basedir, func(path string, info os.FileInfo, err error) error { + go func() { errChan <- walkFn(path, info, err) }() + + select { + case <-ctx.Done(): + if err := ctx.Err(); err != nil { + return err + } + case err := <-errChan: + if err != nil { + return err + } + } + + return nil + }) + if err != nil { + fmt.Println(err) + return err + } + + err = gz.Close() + if err != nil { + return err + } + err = tarball.Close() + if err != nil { + return err + } + + return nil +} |