Skip to content

A couple of small cleanup commits #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 21 additions & 88 deletions pkg/bspatch/bspatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ package bspatch

import (
"bytes"
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"os"

"github.com/dsnet/compress/bzip2"
"github.com/gabstv/go-bsdiff/pkg/util"
Expand All @@ -42,11 +43,11 @@ func Bytes(oldfile, patch []byte) (newfile []byte, err error) {

// Reader applies a BSDIFF4 patch (using oldbin and patchf) to create the newbin
func Reader(oldbin io.Reader, newbin io.Writer, patchf io.Reader) error {
oldbs, err := ioutil.ReadAll(oldbin)
oldbs, err := io.ReadAll(oldbin)
if err != nil {
return err
}
diffbytes, err := ioutil.ReadAll(patchf)
diffbytes, err := io.ReadAll(patchf)
if err != nil {
return err
}
Expand All @@ -59,19 +60,19 @@ func Reader(oldbin io.Reader, newbin io.Writer, patchf io.Reader) error {

// File applies a BSDIFF4 patch (using oldfile and patchfile) to create the newfile
func File(oldfile, newfile, patchfile string) error {
oldbs, err := ioutil.ReadFile(oldfile)
oldbs, err := os.ReadFile(oldfile)
if err != nil {
return fmt.Errorf("could not read oldfile '%v': %v", oldfile, err.Error())
}
patchbs, err := ioutil.ReadFile(patchfile)
patchbs, err := os.ReadFile(patchfile)
if err != nil {
return fmt.Errorf("could not read patchfile '%v': %v", patchfile, err.Error())
}
newbytes, err := patchb(oldbs, patchbs)
if err != nil {
return fmt.Errorf("bspatch: %v", err.Error())
}
if err := ioutil.WriteFile(newfile, newbytes, 0644); err != nil {
if err := os.WriteFile(newfile, newbytes, 0644); err != nil {
return fmt.Errorf("could not create newfile '%v': %v", newfile, err.Error())
}
return nil
Expand All @@ -82,7 +83,6 @@ func patchb(oldfile, patch []byte) ([]byte, error) {
var newsize int
header := make([]byte, 32)
buf := make([]byte, 8)
var lenread int
var i int
ctrl := make([]int, 3)

Expand Down Expand Up @@ -131,6 +131,7 @@ func patchb(oldfile, patch []byte) ([]byte, error) {
if err != nil {
return nil, err
}
defer cpfbz2.Close()
dpf := bytes.NewReader(patch)
if _, err := dpf.Seek(int64(32+bzctrllen), io.SeekStart); err != nil {
return nil, err
Expand All @@ -139,6 +140,7 @@ func patchb(oldfile, patch []byte) ([]byte, error) {
if err != nil {
return nil, err
}
defer dpfbz2.Close()
epf := bytes.NewReader(patch)
if _, err := epf.Seek(int64(32+bzctrllen+bzdatalen), io.SeekStart); err != nil {
return nil, err
Expand All @@ -147,6 +149,7 @@ func patchb(oldfile, patch []byte) ([]byte, error) {
if err != nil {
return nil, err
}
defer epfbz2.Close()

pnew := make([]byte, newsize)

Expand All @@ -156,13 +159,8 @@ func patchb(oldfile, patch []byte) ([]byte, error) {
for newpos < newsize {
// Read control data
for i = 0; i <= 2; i++ {
lenread, err = zreadall(cpfbz2, buf, 8)
if lenread != 8 || (err != nil && err != io.EOF) {
e0 := ""
if err != nil {
e0 = err.Error()
}
return nil, fmt.Errorf("corrupt patch or bzstream ended: %s (read: %v/8)", e0, lenread)
if _, err = io.ReadFull(cpfbz2, buf); err != nil {
return nil, fmt.Errorf("corrupt patch or bzstream ended: %s", err)
}
ctrl[i] = offtin(buf)
}
Expand All @@ -172,14 +170,8 @@ func patchb(oldfile, patch []byte) ([]byte, error) {
}

// Read diff string
// lenread, err = dpfbz2.Read(pnew[newpos : newpos+ctrl[0]])
lenread, err = zreadall(dpfbz2, pnew[newpos:newpos+ctrl[0]], ctrl[0])
if lenread < ctrl[0] || (err != nil && err != io.EOF) {
e0 := ""
if err != nil {
e0 = err.Error()
}
return nil, fmt.Errorf("corrupt patch or bzstream ended (2): %s", e0)
if _, err := io.ReadFull(dpfbz2, pnew[newpos:newpos+ctrl[0]]); err != nil {
return nil, fmt.Errorf("corrupt patch or bzstream ended (2): %s", err)
}
// Add pold data to diff string
for i = 0; i < ctrl[0]; i++ {
Expand All @@ -198,81 +190,22 @@ func patchb(oldfile, patch []byte) ([]byte, error) {
}

// Read extra string
// epfbz2.Read was not reading all the requested bytes, probably an internal buffer limitation ?
// it was encapsulated by zreadall to work around the issue
lenread, err = zreadall(epfbz2, pnew[newpos:newpos+ctrl[1]], ctrl[1])
if lenread < ctrl[1] || (err != nil && err != io.EOF) {
e0 := ""
if err != nil {
e0 = err.Error()
}
return nil, fmt.Errorf("corrupt patch or bzstream ended (3): %s", e0)
if _, err := io.ReadFull(epfbz2, pnew[newpos:newpos+ctrl[1]]); err != nil {
return nil, fmt.Errorf("corrupt patch or bzstream ended (3): %s", err)
}
// Adjust pointers
newpos += ctrl[1]
oldpos += ctrl[2]
}

// Clean up the bzip2 reads
if err = cpfbz2.Close(); err != nil {
return nil, err
}
if err = dpfbz2.Close(); err != nil {
return nil, err
}
if err = epfbz2.Close(); err != nil {
return nil, err
}
cpfbz2 = nil
dpfbz2 = nil
epfbz2 = nil
cpf = nil
dpf = nil
epf = nil

return pnew, nil
}

// offtin reads an int64 (little endian)
// offtin reads an int64 (little endian using a sign-bit, not two's complement)
func offtin(buf []byte) int {

y := int(buf[7] & 0x7f)
y = y * 256
y += int(buf[6])
y = y * 256
y += int(buf[5])
y = y * 256
y += int(buf[4])
y = y * 256
y += int(buf[3])
y = y * 256
y += int(buf[2])
y = y * 256
y += int(buf[1])
y = y * 256
y += int(buf[0])

if (buf[7] & 0x80) != 0 {
y = -y
}
return y
}

func zreadall(r io.Reader, b []byte, expected int) (int, error) {
var allread int
var offset int
for {
nread, err := r.Read(b[offset:])
if nread == expected {
return nread, err
}
if err != nil {
return allread + nread, err
}
allread += nread
if allread >= expected {
return allread, nil
}
offset += nread
v := binary.LittleEndian.Uint64(buf)
if v&(1<<63) != 0 {
return -int(v &^ (1 << 63))
}
return int(v)
}
3 changes: 2 additions & 1 deletion pkg/bspatch/bspatch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"os"
"testing"
Expand Down Expand Up @@ -280,7 +281,7 @@ func TestZReadAll(t *testing.T) {
rr := &lowcaprdr{
read: make([]byte, 1024),
}
nr, err := zreadall(rr, buf, len(buf))
nr, err := io.ReadFull(rr, buf)
if err != nil {
t.Fail()
}
Expand Down