11package main
22
33import (
4- "encoding/json"
5- "errors"
6- "flag"
74 "fmt"
85 "io"
96 "os"
107
118 "github.com/klauspost/compress/zstd"
12- "github.com/lima-vm/go-qcow2reader"
13- "github.com/lima-vm/go-qcow2reader/image"
149 "github.com/lima-vm/go-qcow2reader/image/qcow2"
1510 "github.com/lima-vm/go-qcow2reader/log"
1611)
1712
18- func warn (s string ) {
13+ func logWarn (s string ) {
1914 fmt .Fprintln (os .Stderr , "WARNING: " + s )
2015}
2116
22- func debugPrint (s string ) {
17+ func logDebug (s string ) {
2318 fmt .Fprintln (os .Stderr , "DEBUG: " + s )
2419}
2520
@@ -40,82 +35,48 @@ func newZstdDecompressor(r io.Reader) (io.ReadCloser, error) {
4035 return & zstdDecompressor {dec }, nil
4136}
4237
38+ func usage () {
39+ usage := `Usage: %s COMMAND [OPTIONS...]
40+
41+ Available commands:
42+ info show image information
43+ read read image data and print to stdout
44+ convert convert image to raw format
45+ `
46+ fmt .Fprintf (os .Stderr , usage , os .Args [0 ])
47+ os .Exit (1 )
48+ }
49+
4350func main () {
44- log .SetWarnFunc (warn )
51+ log .SetWarnFunc (logWarn )
4552
4653 // zlib (deflate) decompressor is registered by default, but zstd is not.
4754 qcow2 .SetDecompressor (qcow2 .CompressionTypeZstd , newZstdDecompressor )
4855
49- if err := xmain (); err != nil {
50- fmt .Fprintln (os .Stderr , "ERROR: " + err .Error ())
51- os .Exit (1 )
52- }
53- }
56+ var err error
5457
55- func xmain () error {
56- flag .Usage = func () {
57- fmt .Fprintf (flag .CommandLine .Output (), "Usage: %s [OPTIONS...] FILE\n " , os .Args [0 ])
58- flag .PrintDefaults ()
58+ var cmd string
59+ if len (os .Args ) > 1 {
60+ cmd = os .Args [1 ]
5961 }
60- var (
61- debug bool
62- info bool
63- bufferSize int
64- offset int64
65- length int64
66- )
67- flag .BoolVar (& debug , "debug" , false , "enable printing debug messages" )
68- flag .BoolVar (& info , "info" , false , "print the image info and exit" )
69- flag .IntVar (& bufferSize , "buffer" , 65536 , "buffer size" )
70- flag .Int64Var (& offset , "offset" , 0 , "offset to read" )
71- flag .Int64Var (& length , "length" , - 1 , "length to read" )
72- flag .Parse ()
73- if debug {
74- log .SetDebugFunc (debugPrint )
62+ var args []string
63+ if len (os .Args ) > 2 {
64+ args = os .Args [2 :]
7565 }
7666
77- args := flag .Args ()
78- switch len (args ) {
79- case 0 :
80- return errors .New ("no file was specified" )
81- case 1 :
82- // NOP
67+ switch cmd {
68+ case "info" :
69+ err = cmdInfo (args )
70+ case "read" :
71+ err = cmdRead (args )
72+ case "convert" :
73+ err = cmdConvert (args )
8374 default :
84- return errors .New ("too many files were specified" )
85- }
86- fName := args [0 ]
87-
88- f , err := os .Open (fName )
89- if err != nil {
90- return err
75+ usage ()
9176 }
92- defer f .Close ()
9377
94- img , err := qcow2reader .Open (f )
9578 if err != nil {
96- return err
97- }
98-
99- if info {
100- imgInfo := image .NewImageInfo (img )
101- j , err := json .MarshalIndent (imgInfo , "" , " " )
102- if err != nil {
103- return err
104- }
105- if _ , err = fmt .Println (string (j )); err != nil {
106- return err
107- }
108- if err = img .Readable (); err != nil {
109- warn (err .Error ())
110- }
111- return nil
112- }
113-
114- if length < 0 {
115- length = img .Size ()
79+ fmt .Fprintln (os .Stderr , "ERROR: " + err .Error ())
80+ os .Exit (1 )
11681 }
117- buf := make ([]byte , bufferSize )
118- sr := io .NewSectionReader (img , offset , length )
119- _ , err = io .CopyBuffer (os .Stdout , sr , buf )
120- return err
12182}
0 commit comments