16b74247fb
Some structures use int for sizes and UNIX timestamps. On some platforms, int is 32 bits, so this can lead to the year 2038 issues and overflows when dealing with large containers or layers. Consistently use int64 to store sizes and UNIX timestamps in api/types/types.go. Update related to code accordingly (i.e. strconv.FormatInt instead of strconv.Itoa). Use int64 in progressreader package to avoid integer overflow when dealing with large quantities. Update related code accordingly. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
68 lines
1.8 KiB
Go
68 lines
1.8 KiB
Go
// Package progressreader provides a Reader with a progress bar that can be
|
|
// printed out using the streamformatter package.
|
|
package progressreader
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/docker/docker/pkg/jsonmessage"
|
|
"github.com/docker/docker/pkg/streamformatter"
|
|
)
|
|
|
|
// Config contains the configuration for a Reader with progress bar.
|
|
type Config struct {
|
|
In io.ReadCloser // Stream to read from
|
|
Out io.Writer // Where to send progress bar to
|
|
Formatter *streamformatter.StreamFormatter
|
|
Size int64
|
|
Current int64
|
|
LastUpdate int64
|
|
NewLines bool
|
|
ID string
|
|
Action string
|
|
}
|
|
|
|
// New creates a new Config.
|
|
func New(newReader Config) *Config {
|
|
return &newReader
|
|
}
|
|
|
|
func (config *Config) Read(p []byte) (n int, err error) {
|
|
read, err := config.In.Read(p)
|
|
config.Current += int64(read)
|
|
updateEvery := int64(1024 * 512) //512kB
|
|
if config.Size > 0 {
|
|
// Update progress for every 1% read if 1% < 512kB
|
|
if increment := int64(0.01 * float64(config.Size)); increment < updateEvery {
|
|
updateEvery = increment
|
|
}
|
|
}
|
|
if config.Current-config.LastUpdate > updateEvery || err != nil {
|
|
updateProgress(config)
|
|
config.LastUpdate = config.Current
|
|
}
|
|
|
|
if err != nil && read == 0 {
|
|
updateProgress(config)
|
|
if config.NewLines {
|
|
config.Out.Write(config.Formatter.FormatStatus("", ""))
|
|
}
|
|
}
|
|
return read, err
|
|
}
|
|
|
|
// Close closes the reader (Config).
|
|
func (config *Config) Close() error {
|
|
if config.Current < config.Size {
|
|
//print a full progress bar when closing prematurely
|
|
config.Current = config.Size
|
|
updateProgress(config)
|
|
}
|
|
return config.In.Close()
|
|
}
|
|
|
|
func updateProgress(config *Config) {
|
|
progress := jsonmessage.JSONProgress{Current: config.Current, Total: config.Size}
|
|
fmtMessage := config.Formatter.FormatProgress(config.ID, config.Action, &progress)
|
|
config.Out.Write(fmtMessage)
|
|
}
|