github.com/jlowellwofford/u-root@v1.0.0/cmds/cpio/cpio.go (about)

     1  // Copyright 2013-2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // cpio operates on cpio files using a cpio package
     6  // It only implements basic cpio options.
     7  //
     8  //
     9  // Synopsis:
    10  //     cpio
    11  //
    12  // Description:
    13  //
    14  // Options:
    15  //     o: output an archive to stdout given a pattern
    16  //     i: output files from a stdin stream
    17  //     t: print table of contents
    18  //     -v: debug prints
    19  //
    20  // Bugs: in i mode, it can't use non-seekable stdin, i.e. a pipe. Yep, this sucks.
    21  // But if we implement seek on such things, we have to do it by reading, which
    22  // really sucks. It's doable, we'll do it if we have to, but for now I'd like
    23  // to avoid the complexity. cpio is a 40 year old concept. If you want something
    24  // better, see ../archive which has a VTOC and separates data from metadata (unlike cpio).
    25  // We could test for ESPIPE and fix it that way ... later.
    26  package main
    27  
    28  import (
    29  	"bufio"
    30  	"flag"
    31  	"fmt"
    32  	"io"
    33  	"log"
    34  	"os"
    35  
    36  	"github.com/u-root/u-root/pkg/cpio"
    37  )
    38  
    39  var (
    40  	debug  = func(string, ...interface{}) {}
    41  	d      = flag.Bool("v", false, "Debug prints")
    42  	format = flag.String("H", "newc", "format")
    43  )
    44  
    45  func usage() {
    46  	log.Fatalf("Usage: cpio")
    47  }
    48  
    49  func main() {
    50  	flag.Parse()
    51  	if *d {
    52  		debug = log.Printf
    53  	}
    54  
    55  	a := flag.Args()
    56  	debug("Args %v", a)
    57  	if len(a) < 1 {
    58  		usage()
    59  	}
    60  	op := a[0]
    61  
    62  	archiver, err := cpio.Format(*format)
    63  	if err != nil {
    64  		log.Fatalf("Format %q not supported: %v", *format, err)
    65  	}
    66  
    67  	switch op {
    68  	case "i":
    69  		rr := archiver.Reader(os.Stdin)
    70  		for {
    71  			rec, err := rr.ReadRecord()
    72  			if err == io.EOF {
    73  				break
    74  			}
    75  			if err != nil {
    76  				log.Fatalf("error reading records: %v", err)
    77  			}
    78  			debug("Creating %s\n", rec)
    79  			if err := cpio.CreateFile(rec); err != nil {
    80  				log.Printf("Creating %q failed: %v", rec.Name, err)
    81  			}
    82  		}
    83  
    84  	case "o":
    85  		rw := archiver.Writer(os.Stdout)
    86  		scanner := bufio.NewScanner(os.Stdin)
    87  
    88  		for scanner.Scan() {
    89  			name := scanner.Text()
    90  			rec, err := cpio.GetRecord(name)
    91  			if err != nil {
    92  				log.Fatalf("Getting record of %q failed: %v", name, err)
    93  			}
    94  			if err := rw.WriteRecord(rec); err != nil {
    95  				log.Fatalf("Writing record %q failed: %v", name, err)
    96  			}
    97  		}
    98  
    99  		if err := scanner.Err(); err != nil {
   100  			log.Fatalf("Error reading stdin: %v", err)
   101  		}
   102  		if err := cpio.WriteTrailer(rw); err != nil {
   103  			log.Fatalf("Error writing trailer record: %v", err)
   104  		}
   105  
   106  	case "t":
   107  		rr := archiver.Reader(os.Stdin)
   108  		for {
   109  			rec, err := rr.ReadRecord()
   110  			if err == io.EOF {
   111  				break
   112  			}
   113  			if err != nil {
   114  				log.Fatalf("error reading records: %v", err)
   115  			}
   116  			fmt.Println(rec)
   117  		}
   118  
   119  	default:
   120  		usage()
   121  	}
   122  }