main.go (1604B) - Raw
1 // Package main is a simple command-line application on top of rootfs.Flatten. 2 package main 3 4 import ( 5 "errors" 6 "fmt" 7 "io" 8 "os" 9 "path/filepath" 10 "runtime" 11 12 "git.jakstys.lt/motiejus/undocker/rootfs" 13 ) 14 15 var Version = "unknown" 16 var VersionHash = "unknown" 17 18 const _usage = `Usage: 19 %s <infile> <outfile> 20 21 Flatten a Docker container image to a root file system. 22 23 Arguments: 24 <infile>: Input Docker container. Tarball. 25 <outfile>: Output tarball, the root file system. '-' is stdout. 26 27 undocker %s (%s) 28 Built with %s 29 ` 30 31 func main() { 32 runtime.GOMAXPROCS(1) // no need to create that many threads 33 34 if len(os.Args) != 3 { 35 fmt.Fprintf(os.Stderr, _usage, 36 filepath.Base(os.Args[0]), 37 Version, 38 VersionHash, 39 runtime.Version(), 40 ) 41 os.Exit(1) 42 } 43 44 c := &command{flattener: rootfs.Flatten, Stdout: os.Stdout} 45 if err := c.execute(os.Args[1], os.Args[2]); err != nil { 46 fmt.Fprintf(os.Stderr, "Error: %v\n", err) 47 os.Exit(1) 48 } 49 os.Exit(0) 50 } 51 52 type command struct { 53 flattener func(io.ReadSeeker, io.Writer) error 54 Stdout io.Writer 55 } 56 57 func (c *command) execute(infile string, outfile string) (_err error) { 58 rd, err := os.Open(infile) 59 if err != nil { 60 return err 61 } 62 defer func() { 63 _err = errors.Join(_err, rd.Close()) 64 }() 65 66 var out io.Writer 67 if outfile == "-" { 68 out = c.Stdout 69 } else { 70 outf, err := os.Create(outfile) 71 if err != nil { 72 return fmt.Errorf("create: %w", err) 73 } 74 defer func() { 75 if _err != nil { 76 _err = errors.Join(_err, os.Remove(outfile)) 77 } else { 78 _err = errors.Join(_err, outf.Close()) 79 } 80 }() 81 out = outf 82 } 83 84 return c.flattener(rd, out) 85 }