func TestVerifyChecksumPatchNegative(t *testing.T) { t.Parallel() fName := "TestVerifyChecksumPatchNegative" defer cleanup(fName) writeOldFile(fName, t) checksum, err := ChecksumForBytes(newFile) if err != nil { t.Fatalf("Failed to compute checksum: %v", err) } patch := new(bytes.Buffer) anotherFile := []byte{0x77, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66} err = binarydist.Diff(bytes.NewReader(oldFile), bytes.NewReader(anotherFile), patch) if err != nil { t.Fatalf("Failed to create patch: %v", err) } up := New().Target(fName).ApplyPatch(PATCHTYPE_BSDIFF).VerifyChecksum(checksum) err, _ = up.FromStream(bytes.NewReader(patch.Bytes())) if err == nil { t.Fatalf("Failed to detect patch to wrong file!") } }
func generate_diff(file string) string { t := time.Now() name := file + t.String() patch, err := os.OpenFile(".smog/"+name, os.O_CREATE|os.O_WRONLY, 0777) if err != nil { log.Fatal(err) } defer patch.Close() old, err := os.Open(".smog/" + file) if err != nil { log.Fatal(err) } defer old.Close() curr, err := os.Open(file) if err != nil { log.Fatal(err) } defer curr.Close() err = binarydist.Diff(old, curr, patch) if err != nil { log.Fatal(err) } return name }
func computeAndStorePatch(a, b release) error { ar := newGzReader(fetch(s3DistURL+a.Gzname(), nil)) defer ar.Close() br := newGzReader(fetch(s3DistURL+b.Gzname(), nil)) defer br.Close() patch := new(bytes.Buffer) if err := binarydist.Diff(ar, br, patch); err != nil { return err } return s3put(patch, s3PatchURL+patchFilename(a.Cmd, a.Plat, a.Ver, b.Ver)) }
func TestApplyPatch(t *testing.T) { t.Parallel() fName := "TestApplyPatch" defer cleanup(fName) writeOldFile(fName, t) patch := new(bytes.Buffer) err := binarydist.Diff(bytes.NewReader(oldFile), bytes.NewReader(newFile), patch) if err != nil { t.Fatalf("Failed to create patch: %v", err) } up := New().Target(fName).ApplyPatch(PATCHTYPE_BSDIFF) err, _ = up.FromStream(bytes.NewReader(patch.Bytes())) validateUpdate(fName, err, t) }
func computeAndStorePatch(a, b release) error { var wg sync.WaitGroup var ar, br io.ReadCloser wg.Add(2) go func() { ar = newGzReader(fetch(s3DistURL+a.Gzname(), nil)) wg.Done() }() go func() { br = newGzReader(fetch(s3DistURL+b.Gzname(), nil)) wg.Done() }() wg.Wait() defer ar.Close() defer br.Close() patch := new(bytes.Buffer) if err := binarydist.Diff(ar, br, patch); err != nil { return err } return s3put(patch, s3PatchURL+patchFilename(a.Cmd, a.Plat, a.Ver, b.Ver)) }
func createUpdate(cmdName, path string, platform string) { c := current{Version: version, Sha256: generateSha256(path)} b, err := json.MarshalIndent(c, "", " ") if err != nil { fmt.Println("error:", err) } if err := os.MkdirAll(filepath.Join(genDir, platform), 0700); err != nil { log.Fatal(err) } err = ioutil.WriteFile(filepath.Join(genDir, platform, cmdName+".json"), b, 0755) if err != nil { panic(err) } os.MkdirAll(filepath.Join(genDir, version, platform), 0755) var buf bytes.Buffer w := gzip.NewWriter(&buf) f, err := ioutil.ReadFile(path) if err != nil { panic(err) } w.Write(f) w.Close() // You must close this first to flush the bytes to the buffer. err = ioutil.WriteFile(filepath.Join(genDir, version, platform, cmdName+".gz"), buf.Bytes(), 0755) files, err := ioutil.ReadDir(genDir) if err != nil { fmt.Println(err) } for _, file := range files { if file.IsDir() == false { continue } if file.Name() == version { continue } os.Mkdir(filepath.Join(genDir, file.Name(), version, platform), 0755) fName := filepath.Join(genDir, file.Name(), platform, cmdName+".gz") old, err := os.Open(fName) if err != nil { // Don't have an old release for this os/arch, continue on continue } fName = filepath.Join(genDir, version, platform, cmdName+".gz") newF, err := os.Open(fName) if err != nil { fmt.Fprintf(os.Stderr, "Can't open %s: error: %s\n", fName, err) os.Exit(1) } ar := newGzReader(old) defer ar.Close() br := newGzReader(newF) defer br.Close() patch := new(bytes.Buffer) if err := binarydist.Diff(ar, br, patch); err != nil { panic(err) } ioutil.WriteFile(filepath.Join(genDir, file.Name(), version, platform, cmdName), patch.Bytes(), 0755) } }
func createUpdate(path string, platform string, numDiffs int) { c := current{Version: version, Sha256: generateSha256(path)} b, err := json.MarshalIndent(c, "", " ") if err != nil { fmt.Println("error:", err) } err = ioutil.WriteFile(filepath.Join(genDir, platform+".json"), b, 0755) if err != nil { panic(err) } os.MkdirAll(filepath.Join(genDir, version), 0755) var buf bytes.Buffer w := gzip.NewWriter(&buf) f, err := ioutil.ReadFile(path) if err != nil { panic(err) } w.Write(f) w.Close() // You must close this first to flush the bytes to the buffer. err = ioutil.WriteFile(filepath.Join(genDir, version, platform+".gz"), buf.Bytes(), 0755) files, err := ioutil.ReadDir(genDir) if err != nil { fmt.Println(err) } // Build a list of old releases available for this platform, using the // full release file as timestamp of the release var releases oldReleasesByTime for _, file := range files { if file.IsDir() && file.Name() != version { f, err := os.Stat(filepath.Join(genDir, file.Name(), platform+".gz")) if err == nil { releases = append(releases, oldRelease{ dir: file, mtime: f.ModTime(), }) } } } sort.Sort(releases) if numDiffs >= 0 { releases = releases[len(releases)-numDiffs:] } for _, rel := range releases { name := rel.dir.Name() os.Mkdir(filepath.Join(genDir, name, version), 0755) fName := filepath.Join(genDir, name, platform+".gz") old, err := os.Open(fName) if err != nil { // Don't have an old release for this os/arch, continue on continue } fName = filepath.Join(genDir, version, platform+".gz") newF, err := os.Open(fName) if err != nil { fmt.Fprintf(os.Stderr, "Can't open %s: error: %s\n", fName, err) os.Exit(1) } fmt.Printf("Generating delta: %s, %s->%s\n", platform, name, version) ar := newGzReader(old) defer ar.Close() br := newGzReader(newF) defer br.Close() patch := new(bytes.Buffer) if err := binarydist.Diff(ar, br, patch); err != nil { panic(err) } ioutil.WriteFile(filepath.Join(genDir, name, version, platform), patch.Bytes(), 0755) } }
func CreatePatch(job CreatePatchJob) (CreatePatchResult, error) { var emptyResult = CreatePatchResult{} logstr := fmt.Sprintf("%s -> %s (%s)", job.OldVersion, job.NewVersion, job.Artifact) outfile := filepath.Join(diffsDir, job.Artifact, job.OldVersion, job.NewVersion) lg.V(10).Infoln("load new binary into memory", logstr) var newData []byte { var err error newData, err = ioutil.ReadFile(job.NewBinary) if err != nil { return emptyResult, nil } } lg.V(10).Infoln("shasum new", logstr) var latestSumBytes []byte { h := sha256.New() h.Write(newData) latestSumBytes = h.Sum(nil) } latestSum := base64.RawURLEncoding.EncodeToString( latestSumBytes) lg.V(10).Infoln("sign new", logstr) var latestSig string { privateKey, err := upgradebin.DecodePrivateKey([]byte(job.PrivateKey)) if err != nil { return emptyResult, err } latestSig = base64.RawURLEncoding.EncodeToString( ed25519.Sign(privateKey, latestSumBytes)[:]) } var diff []byte { lg.V(10).Infoln("generate diff", logstr) var patch bytes.Buffer newFile := bytes.NewReader(newData) oldFile, err := os.Open(job.OldBinary) if err != nil { return emptyResult, nil } defer oldFile.Close() if err := binarydist.Diff(oldFile, newFile, &patch); err != nil { return emptyResult, nil } diff = patch.Bytes() } { lg.V(10).Infoln("write diff", logstr) if err := os.MkdirAll(filepath.Dir(outfile), 0775); err != nil { return emptyResult, err } if err := ioutil.WriteFile(outfile, diff, 0775); err != nil { return emptyResult, err } } res := CreatePatchResult{ job: job, Artifact: job.Artifact, NewVersion: job.NewVersion, OldVersion: job.OldVersion, SHA256Sum: latestSum, ED25519Signature: latestSig, DiffFile: outfile, } data, err := json.MarshalIndent(res, "", " ") if err != nil { return emptyResult, err } err = ioutil.WriteFile(fmt.Sprintf("%s.json", outfile), data, 0775) if err != nil { return emptyResult, err } lg.Infoln("done", logstr) return res, nil }