package steam import ( "archive/tar" "io" "path/filepath" "time" ) const ( defaultDirectoryMode = 0775 defaultFileMode = 0644 ) func (l *Library) Package(game string, wr io.Writer) error { l.m.Lock() if _, ok := l.Games()[game]; !ok { l.m.Unlock() return E_GameDoesNotExist } g := l.Games()[game] j := newJob("package", g) defer j.done() l.status.addJob(j) j.setSize(g.GetSizeBytes()) // Invert the writer, so we can break up the copy and get progress // information in here rdr, pwrtr := io.Pipe() go func() { err := l.packagePrimitive(j, g, pwrtr) if err != nil { j.addError(err) } }() var total int64 for { n, err := io.CopyN(wr, rdr, updateEveryNBytes) if err == io.EOF { break } if err != nil { j.addError(err) return err } total += n j.setTransferred(total) elapsedSeconds := time.Since(*j.StartTime()).Seconds() rate := float64(total) / elapsedSeconds // fmt.Println("rate in bytes/second: ", formatBytes(int64(rate))) estSize := j.GetSize() if estSize == nil { j.addError(E_NoEstimatedSize) continue } remainingBytes := float64(*estSize - total) // fmt.Println("remaining bytes: ", formatBytes(int64(remainingBytes))) seconds := remainingBytes / rate duration := time.Duration(seconds * 1000 * 1000 * 1000) // fmt.Println("Raw duration: ", duration) j.setETA(duration) } return nil } // Package writes the package to wr, returning errors if any func (l *Library) packagePrimitive(g *Game, wr io.WriteCloser) error { acf, err := FindACF(l.folder, g.Name) if err != nil { j.addError(err) return err } twriter := tar.NewWriter(wr) paths := []string{ filepath.Join(l.folder, "common", g.Name), acf, } for _, pth := range paths { err := filepath.Walk(pth, tarWalkfn(twriter, l.folder)) if err != nil { j.addError(err) return err } } err = twriter.Flush() if err != nil { j.addError(err) return err } err = twriter.Close() if err != nil { j.addError(err) return err } err = wr.Close() if err != nil { j.addError(err) return err } return err }