@@ -102,91 +102,102 @@ func snapshotDir(config *config.Control, create bool) (string, error) {
102102
103103// compressSnapshot compresses the given snapshot and provides the
104104// caller with the path to the file.
105- func (e * ETCD ) compressSnapshot (snapshotDir , snapshotName , snapshotPath string , now time.Time ) (string , error ) {
106- logrus .Info ("Compressing etcd snapshot file: " + snapshotName )
105+ func (e * ETCD ) compressSnapshot (snapshotDir , snapshotFilename string , mtime time.Time ) (zipPath string , err error ) {
106+ logrus .Info ("Compressing etcd snapshot file: " + snapshotFilename )
107+ snapshotPath := filepath .Join (snapshotDir , snapshotFilename )
108+ zipPath = snapshotPath + snapshot .CompressedExtension
107109
108- zippedSnapshotName := snapshotName + snapshot .CompressedExtension
109- zipPath := filepath .Join (snapshotDir , zippedSnapshotName )
110+ defer func () {
111+ if err != nil {
112+ os .Remove (zipPath )
113+ }
114+ }()
110115
111- zf , err := os .Create ( zipPath )
116+ sf , err := os .Open ( snapshotPath )
112117 if err != nil {
113118 return "" , err
114119 }
115- defer zf .Close ()
116-
117- zipWriter := zip .NewWriter (zf )
118- defer zipWriter .Close ()
120+ defer sf .Close ()
119121
120- uncompressedPath := filepath .Join (snapshotDir , snapshotName )
121- fileToZip , err := os .Open (uncompressedPath )
122+ fi , err := sf .Stat ()
122123 if err != nil {
123- os .Remove (zipPath )
124124 return "" , err
125125 }
126- defer fileToZip .Close ()
127126
128- info , err := fileToZip . Stat ( )
127+ of , err := os . Create ( zipPath )
129128 if err != nil {
130- os .Remove (zipPath )
131129 return "" , err
132130 }
131+ defer of .Close ()
133132
134- header , err := zip .FileInfoHeader (info )
133+ zw := zip .NewWriter (of )
134+ defer zw .Close ()
135+
136+ zfi , err := zip .FileInfoHeader (fi )
135137 if err != nil {
136- os .Remove (zipPath )
137138 return "" , err
138139 }
139140
140- header .Name = snapshotName
141- header .Method = zip .Deflate
142- header .Modified = now
141+ zfi .Name = snapshotFilename
142+ zfi .Method = zip .Deflate
143+ zfi .Modified = mtime
143144
144- writer , err := zipWriter .CreateHeader (header )
145+ hw , err := zw .CreateHeader (zfi )
145146 if err != nil {
146- os .Remove (zipPath )
147147 return "" , err
148148 }
149- _ , err = io .Copy (writer , fileToZip )
150149
150+ _ , err = io .Copy (hw , sf )
151151 return zipPath , err
152152}
153153
154154// decompressSnapshot decompresses the given snapshot and provides the caller
155155// with the full path to the uncompressed snapshot.
156- func (e * ETCD ) decompressSnapshot (snapshotDir , snapshotFile string ) (string , error ) {
157- logrus .Info ("Decompressing etcd snapshot file: " + snapshotFile )
156+ func (e * ETCD ) decompressSnapshot (snapshotDir , snapshotFilename string ) (unzipPath string , err error ) {
157+ logrus .Info ("Decompressing etcd snapshot file: " + snapshotFilename )
158+ snapshotPath := filepath .Join (snapshotDir , snapshotFilename )
159+ unzipPath = strings .TrimSuffix (snapshotPath , snapshot .CompressedExtension )
160+
161+ defer func () {
162+ if err != nil {
163+ os .Remove (unzipPath )
164+ }
165+ }()
158166
159- r , err := zip . OpenReader ( snapshotFile )
167+ sf , err := os . Open ( snapshotPath )
160168 if err != nil {
161169 return "" , err
162170 }
163- defer r .Close ()
171+ defer sf .Close ()
164172
165- var decompressed * os.File
166- for _ , sf := range r .File {
167- decompressed , err = os .OpenFile (strings .Replace (sf .Name , snapshot .CompressedExtension , "" , - 1 ), os .O_WRONLY | os .O_CREATE | os .O_TRUNC , sf .Mode ())
168- if err != nil {
169- return "" , err
170- }
173+ fi , err := sf .Stat ()
174+ if err != nil {
175+ return "" , err
176+ }
171177
172- //revive:disable-next-line:defer
173- defer decompressed .Close ()
178+ zf , err := zip .NewReader (sf , fi .Size ())
179+ if err != nil {
180+ return "" , err
181+ }
174182
175- ss , err := sf .Open ()
176- if err != nil {
177- return "" , err
178- }
183+ if len (zf .File ) != 1 {
184+ return "" , errors .New ("unexpected compressed etcd snapshot contents" )
185+ }
179186
180- //revive:disable-next-line:defer
181- defer ss .Close ()
187+ cf , err := zf .File [0 ].Open ()
188+ if err != nil {
189+ return "" , err
190+ }
191+ defer cf .Close ()
182192
183- if _ , err := io .Copy (decompressed , ss ); err != nil {
184- os .Remove (decompressed .Name ())
185- return "" , err
186- }
193+ of , err := os .OpenFile (unzipPath , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , 0600 )
194+ if err != nil {
195+ return "" , err
187196 }
197+ defer of .Close ()
188198
189- return decompressed .Name (), nil
199+ _ , err = io .Copy (of , cf )
200+ return unzipPath , err
190201}
191202
192203// Snapshot attempts to save a new snapshot to the configured directory, and then clean up any old and failed
@@ -289,7 +300,7 @@ func (e *ETCD) snapshot(ctx context.Context) (_ *managed.SnapshotResult, rerr er
289300 // If the snapshot attempt was successful, sf will be nil as we did not set it to store the error message.
290301 if sf == nil {
291302 if e .config .EtcdSnapshotCompress {
292- zipPath , err := e .compressSnapshot (snapshotDir , snapshotName , snapshotPath , now )
303+ zipPath , err := e .compressSnapshot (snapshotDir , snapshotName , now )
293304
294305 // ensure that the unncompressed snapshot is cleaned up even if compression fails
295306 if err := os .Remove (snapshotPath ); err != nil && ! os .IsNotExist (err ) {
0 commit comments