github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/system/backup/zip.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2016-2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package backup 20 21 import ( 22 "archive/zip" 23 "io" 24 "os" 25 "path/filepath" 26 "strings" 27 ) 28 29 func unzip(archive, target string) error { 30 reader, err := zip.OpenReader(archive) 31 if err != nil { 32 return err 33 } 34 defer reader.Close() 35 36 if err := os.MkdirAll(target, 0755); err != nil { 37 return err 38 } 39 40 for _, file := range reader.File { 41 path := filepath.Join(target, file.Name) 42 if file.FileInfo().IsDir() { 43 _ = os.MkdirAll(path, file.Mode()) 44 continue 45 } 46 47 fileReader, err := file.Open() 48 if err != nil { 49 return err 50 } 51 defer fileReader.Close() 52 53 targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, file.Mode()) 54 if err != nil { 55 return err 56 } 57 defer targetFile.Close() 58 59 if _, err := io.Copy(targetFile, fileReader); err != nil { 60 return err 61 } 62 } 63 64 return nil 65 } 66 67 func zipit(sources []string, target string) error { 68 zipfile, err := os.Create(target) 69 if err != nil { 70 return err 71 } 72 defer zipfile.Close() 73 74 archive := zip.NewWriter(zipfile) 75 defer archive.Close() 76 77 for _, source := range sources { 78 info, err := os.Stat(source) 79 if err != nil { 80 return nil 81 } 82 83 var baseDir string 84 if info.IsDir() { 85 baseDir = filepath.Base(source) 86 } 87 88 _ = filepath.Walk(source, func(path string, info os.FileInfo, err error) error { 89 if err != nil { 90 return err 91 } 92 93 header, err := zip.FileInfoHeader(info) 94 if err != nil { 95 return err 96 } 97 98 if baseDir != "" { 99 header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source)) 100 } 101 102 if info.IsDir() { 103 header.Name += string(filepath.Separator) 104 } else { 105 header.Method = zip.Deflate 106 } 107 108 writer, err := archive.CreateHeader(header) 109 if err != nil { 110 return err 111 } 112 113 if info.IsDir() { 114 return nil 115 } 116 117 file, err := os.Open(path) 118 if err != nil { 119 return err 120 } 121 defer file.Close() 122 _, err = io.Copy(writer, file) 123 return err 124 }) 125 126 } 127 128 return err 129 } 130 131 func checkZip(archive string) (ok bool, err error) { 132 var reader *zip.ReadCloser 133 reader, err = zip.OpenReader(archive) 134 if err != nil { 135 return 136 } 137 defer reader.Close() 138 ok = len(reader.File) > 0 139 return 140 }