Skip to content

Instantly share code, notes, and snippets.

@zyla
Created May 14, 2018 21:30
Show Gist options
  • Save zyla/49459645f50a546324bc8680ce1d4f81 to your computer and use it in GitHub Desktop.
Save zyla/49459645f50a546324bc8680ce1d4f81 to your computer and use it in GitHub Desktop.
// Binary ddrescue_extract reads finished blocks from a ddrescue-produced image.
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
)
func main() {
args := os.Args
if len(args) != 3 {
usage()
}
imageFilename := args[1]
imageFile, err := os.Open(imageFilename)
if err != nil {
log.Fatalf("Can't open image file: %s", err)
}
defer imageFile.Close()
mapFilename := args[2]
mapFile, err := os.Open(mapFilename)
if err != nil {
log.Fatalf("Can't open mapfile: %s", err)
}
defer mapFile.Close()
b := bufio.NewReader(mapFile)
// skip status line
readLine(b)
for {
line, err := readLine(b)
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("Error reading from mapfile %s: %v", mapFilename, err)
}
var start, nbytes uint64
var status byte
if n, err := fmt.Sscanf(line, "0x%x 0x%x %c", &start, &nbytes, &status); err != nil {
log.Fatalf("Error scanning line %q: %v\nScanned items: %d", line, err, n)
}
if status != '+' {
continue
}
log.Printf("Reading %d bytes at offset %d; status=%c\n", nbytes, start, status)
imageFile.Seek(int64(start), os.SEEK_SET)
if _, err := io.CopyN(os.Stdout, imageFile, int64(nbytes)); err != nil {
log.Fatalf("Error copying block at %d: %v", start, err)
}
}
}
// readLine returns next line from the reader that isn't a comment (doesn't start with "#").
func readLine(b *bufio.Reader) (string, error) {
for {
line, err := b.ReadString('\n')
if err != nil {
return "", err
}
if line[0] != '#' {
return line, nil
}
}
}
func usage() {
fmt.Fprintln(os.Stderr, "Usage: ddrescue_extract <imagefile> <mapfile>")
os.Exit(1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment