github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/app/lib/filesystem/zip.go (about) 1 // Package filesystem - Content managed by Project Forge, see [projectforge.md] for details. 2 package filesystem 3 4 import ( 5 "archive/zip" 6 "io" 7 "os" 8 "path/filepath" 9 "strings" 10 11 "github.com/pkg/errors" 12 13 "github.com/kyleu/dbaudit/app/util" 14 ) 15 16 func (f *FileSystem) UnzipToDir(src string, dest string) (*util.OrderedMap[int64], error) { 17 r, err := f.FileReader(src) 18 if err != nil { 19 return nil, err 20 } 21 22 zr, err := zip.NewReader(r, int64(f.Size(src))) 23 if err != nil { 24 return nil, err 25 } 26 27 err = f.CreateDirectory(dest) 28 if err != nil { 29 return nil, err 30 } 31 32 extractAndWriteFile := func(zf *zip.File) (int64, error) { 33 rc, err := zf.Open() 34 if err != nil { 35 return 0, err 36 } 37 defer func() { 38 if err := rc.Close(); err != nil { 39 panic(err) 40 } 41 }() 42 43 path := filepath.Join(dest, zf.Name) 44 45 if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) { 46 return 0, errors.Errorf("illegal file path: %s", path) 47 } 48 49 var sz int64 50 if zf.FileInfo().IsDir() { 51 sz = -1 52 _ = f.CreateDirectory(path) 53 } else { 54 _ = f.CreateDirectory(filepath.Dir(path)) 55 df, err := f.FileWriter(path, true, false) 56 if err != nil { 57 return 0, err 58 } 59 defer func() { 60 _ = df.Close() 61 }() 62 sz, err = io.Copy(df, rc) 63 if err != nil { 64 return 0, err 65 } 66 } 67 return sz, nil 68 } 69 70 ret := util.NewOrderedMap[int64](false, len(zr.File)) 71 for _, f := range zr.File { 72 fsz, err := extractAndWriteFile(f) 73 if err != nil { 74 return nil, err 75 } 76 ret.Append(f.Name, fsz) 77 } 78 return ret, nil 79 }