// ExtractTarStreamFromTarReader extracts files from a given tar stream. // Times out if reading from the stream for any given file // exceeds the value of timeout func (t *stiTar) ExtractTarStreamFromTarReader(dir string, tarReader Reader, logger io.Writer) error { err := util.TimeoutAfter(t.timeout, "", func(timeoutTimer *time.Timer) error { for { header, err := tarReader.Next() if !timeoutTimer.Stop() { return &util.TimeoutError{} } timeoutTimer.Reset(t.timeout) if err == io.EOF { return nil } if err != nil { glog.Errorf("Error reading next tar header: %v", err) return err } if header.FileInfo().IsDir() { dirPath := filepath.Join(dir, header.Name) glog.V(3).Infof("Creating directory %s", dirPath) if err = os.MkdirAll(dirPath, 0700); err != nil { glog.Errorf("Error creating dir %q: %v", dirPath, err) return err } } else { fileDir := filepath.Dir(header.Name) dirPath := filepath.Join(dir, fileDir) glog.V(3).Infof("Creating directory %s", dirPath) if err = os.MkdirAll(dirPath, 0700); err != nil { glog.Errorf("Error creating dir %q: %v", dirPath, err) return err } if header.Typeflag == tar.TypeSymlink { if err := t.extractLink(dir, header, tarReader); err != nil { glog.Errorf("Error extracting link %q: %v", header.Name, err) return err } continue } logFile(logger, header.Name) if err := t.extractFile(dir, header, tarReader); err != nil { glog.Errorf("Error extracting file %q: %v", header.Name, err) return err } } } }) if err != nil { glog.Error("Error extracting tar stream") } else { glog.V(2).Info("Done extracting tar stream") } if util.IsTimeoutError(err) { err = s2ierr.NewTarTimeoutError() } return err }
// ExtractTarStream extracts files from a given tar stream. // Times out if reading from the stream for any given file // exceeds the value of timeout func (t *stiTar) ExtractTarStream(dir string, reader io.Reader) error { tarReader := tar.NewReader(reader) errorChannel := make(chan error) timeout := t.timeout timeoutTimer := time.NewTimer(timeout) go func() { for { header, err := tarReader.Next() timeoutTimer.Reset(timeout) if err == io.EOF { errorChannel <- nil break } if err != nil { glog.Errorf("Error reading next tar header: %v", err) errorChannel <- err break } if header.FileInfo().IsDir() { dirPath := filepath.Join(dir, header.Name) if err = os.MkdirAll(dirPath, 0700); err != nil { glog.Errorf("Error creating dir %s: %v", dirPath, err) errorChannel <- err break } } else { fileDir := filepath.Dir(header.Name) dirPath := filepath.Join(dir, fileDir) if err = os.MkdirAll(dirPath, 0700); err != nil { glog.Errorf("Error creating dir %s: %v", dirPath, err) errorChannel <- err break } if err := extractFile(dir, header, tarReader); err != nil { glog.Errorf("Error extracting file %s: %v", header.Name, err) errorChannel <- err } } } }() for { select { case err := <-errorChannel: if err != nil { glog.Errorf("Error extracting tar stream") } else { glog.V(2).Infof("Done extracting tar stream") } return err case <-timeoutTimer.C: return errors.NewTarTimeoutError() } } }
// ExtractTarStreamFromTarReader extracts files from a given tar stream. // Times out if reading from the stream for any given file // exceeds the value of timeout func (t *stiTar) ExtractTarStreamFromTarReader(dir string, tarReader Reader, logger io.Writer) error { errorChannel := make(chan error, 1) timeoutTimer := time.NewTimer(t.timeout) go func() { for { header, err := tarReader.Next() if !timeoutTimer.Stop() { break } timeoutTimer.Reset(t.timeout) if err == io.EOF { errorChannel <- nil break } if err != nil { glog.Errorf("Error reading next tar header: %v", err) errorChannel <- err break } if header.FileInfo().IsDir() { dirPath := filepath.Join(dir, header.Name) glog.V(3).Infof("Creating directory %s", dirPath) if err = os.MkdirAll(dirPath, 0700); err != nil { glog.Errorf("Error creating dir %q: %v", dirPath, err) errorChannel <- err break } } else { fileDir := filepath.Dir(header.Name) dirPath := filepath.Join(dir, fileDir) glog.V(3).Infof("Creating directory %s", dirPath) if err = os.MkdirAll(dirPath, 0700); err != nil { glog.Errorf("Error creating dir %q: %v", dirPath, err) errorChannel <- err break } if header.Typeflag == tar.TypeSymlink { if err := extractLink(dir, header, tarReader); err != nil { glog.Errorf("Error extracting link %q: %v", header.Name, err) errorChannel <- err break } continue } logFile(logger, header.Name) if err := extractFile(dir, header, tarReader); err != nil { glog.Errorf("Error extracting file %q: %v", header.Name, err) errorChannel <- err break } } } }() for { select { case err := <-errorChannel: if err != nil { glog.Error("Error extracting tar stream") } else { glog.V(2).Info("Done extracting tar stream") } return err case <-timeoutTimer.C: return errors.NewTarTimeoutError() } } }