forked from oras-project/oras
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gunzip and untar passthrough writers (oras-project#191)
Signed-off-by: Avi Deitcher <[email protected]>
- Loading branch information
Showing
3 changed files
with
116 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package content | ||
|
||
import ( | ||
"compress/gzip" | ||
"fmt" | ||
"io" | ||
|
||
"github.com/containerd/containerd/content" | ||
) | ||
|
||
// NewGunzipWriter wrap a writer with a gunzip, so that the stream is gunzipped | ||
func NewGunzipWriter(writer content.Writer, blocksize int) content.Writer { | ||
if blocksize == 0 { | ||
blocksize = DefaultBlocksize | ||
} | ||
return NewPassthroughWriter(writer, func(r io.Reader, w io.Writer, done chan<- error) { | ||
gr, err := gzip.NewReader(r) | ||
if err != nil { | ||
done <- fmt.Errorf("error creating gzip reader: %v", err) | ||
return | ||
} | ||
// write out the uncompressed data | ||
b := make([]byte, blocksize, blocksize) | ||
for { | ||
var n int | ||
n, err = gr.Read(b) | ||
if err != nil && err != io.EOF { | ||
err = fmt.Errorf("GunzipWriter data read error: %v\n", err) | ||
break | ||
} | ||
l := n | ||
if n > len(b) { | ||
l = len(b) | ||
} | ||
if _, err2 := w.Write(b[:l]); err2 != nil { | ||
err = fmt.Errorf("GunzipWriter: error writing to underlying writer: %v", err2) | ||
break | ||
} | ||
if err == io.EOF { | ||
// clear the error | ||
err = nil | ||
break | ||
} | ||
} | ||
gr.Close() | ||
done <- err | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package content | ||
|
||
import ( | ||
"archive/tar" | ||
"fmt" | ||
"io" | ||
|
||
"github.com/containerd/containerd/content" | ||
) | ||
|
||
// NewUntarWriter wrap a writer with an untar, so that the stream is untarred | ||
func NewUntarWriter(writer content.Writer, blocksize int) content.Writer { | ||
if blocksize == 0 { | ||
blocksize = DefaultBlocksize | ||
} | ||
return NewPassthroughWriter(writer, func(r io.Reader, w io.Writer, done chan<- error) { | ||
tr := tar.NewReader(r) | ||
var err error | ||
for { | ||
_, err := tr.Next() | ||
if err == io.EOF { | ||
// clear the error, since we do not pass an io.EOF | ||
err = nil | ||
break // End of archive | ||
} | ||
if err != nil { | ||
// pass the error on | ||
err = fmt.Errorf("UntarWriter tar file header read error: %v", err) | ||
break | ||
} | ||
// write out the untarred data | ||
// we can handle io.EOF, just go to the next file | ||
// any other errors should stop and get reported | ||
b := make([]byte, blocksize, blocksize) | ||
for { | ||
var n int | ||
n, err = tr.Read(b) | ||
if err != nil && err != io.EOF { | ||
err = fmt.Errorf("UntarWriter file data read error: %v\n", err) | ||
break | ||
} | ||
l := n | ||
if n > len(b) { | ||
l = len(b) | ||
} | ||
if _, err2 := w.Write(b[:l]); err2 != nil { | ||
err = fmt.Errorf("UntarWriter error writing to underlying writer: %v", err2) | ||
break | ||
} | ||
if err == io.EOF { | ||
// go to the next file | ||
break | ||
} | ||
} | ||
// did we break with a non-nil and non-EOF error? | ||
if err != nil && err != io.EOF { | ||
break | ||
} | ||
} | ||
done <- err | ||
}) | ||
} |