github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/system/backup/file.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 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 "fmt" 23 "io" 24 "os" 25 "path" 26 "path/filepath" 27 "sort" 28 "strings" 29 30 "github.com/pkg/errors" 31 ) 32 33 func splitFile(inputPath string, chunkSize int64) ([]string, error) { 34 inputFile, err := os.Open(inputPath) 35 if err != nil { 36 return nil, err 37 } 38 defer inputFile.Close() 39 40 chunkSize = 1024 * 1024 * chunkSize 41 42 fileInfo, err := os.Stat(inputPath) 43 if err != nil { 44 return nil, err 45 } 46 47 fileSize := fileInfo.Size() 48 numChunks := (fileSize + chunkSize - 1) / chunkSize 49 50 tmpDir := path.Join(os.TempDir(), "smart_home") 51 if err = os.MkdirAll(tmpDir, 0755); err != nil { 52 return nil, err 53 } 54 55 var fileList []string 56 fileName := strings.ReplaceAll(fileInfo.Name(), ".zip", "") 57 for i := int64(0); i < numChunks; i++ { 58 outputPath := fmt.Sprintf("%s_part%d.dat", fileName, i+1) 59 outputPath = path.Join(tmpDir, outputPath) 60 61 // Создаем новый файл для части 62 outputFile, err := os.Create(outputPath) 63 if err != nil { 64 return nil, err 65 } 66 defer outputFile.Close() 67 68 // Читаем кусок данных из исходного файла 69 bufferSize := chunkSize 70 if i == numChunks-1 { 71 bufferSize = fileSize - i*chunkSize 72 } 73 74 buffer := make([]byte, bufferSize) 75 _, err = inputFile.Read(buffer) 76 if err != nil && err != io.EOF { 77 return nil, err 78 } 79 80 // Записываем кусок в новый файл 81 _, err = outputFile.Write(buffer) 82 if err != nil { 83 return nil, err 84 } 85 86 fileList = append(fileList, outputPath) 87 } 88 89 return fileList, nil 90 } 91 92 func joinFiles(inputPattern, dir string) (string, error) { 93 94 matches, err := filepath.Glob(inputPattern) 95 if err != nil { 96 return "", err 97 } 98 99 if len(matches) == 0 || len(matches) == 1 { 100 return "", errors.New("no matches or less then 2") 101 } 102 103 sort.Strings(matches) 104 105 fmt.Println(matches) 106 107 params := strings.Split(matches[0], "_part") 108 if len(params) < 2 { 109 return "", err 110 } 111 112 fileName := path.Join(dir, filepath.Base(fmt.Sprintf("%s.zip", params[0]))) 113 outputFile, err := os.Create(fileName) 114 if err != nil { 115 return "", err 116 } 117 defer outputFile.Close() 118 119 for _, match := range matches { 120 inputFile, err := os.Open(match) 121 if err != nil { 122 return "", err 123 } 124 defer inputFile.Close() 125 126 _, err = io.Copy(outputFile, inputFile) 127 if err != nil { 128 return "", err 129 } 130 } 131 132 return fileName, nil 133 }