Home | History | Annotate | Download | only in exec
      1 // Copyright 2009 The Go 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 // Package exec runs external commands. It wraps os.StartProcess to make it
      6 // easier to remap stdin and stdout, connect I/O with pipes, and do other
      7 // adjustments.
      8 //
      9 // Note that the examples in this package assume a Unix system.
     10 // They may not run on Windows, and they do not run in the Go Playground
     11 // used by golang.org and godoc.org.
     12 package exec
     13 
     14 import (
     15 	"bytes"
     16 	"context"
     17 	"errors"
     18 	"io"
     19 	"os"
     20 	"path/filepath"
     21 	"runtime"
     22 	"strconv"
     23 	"strings"
     24 	"sync"
     25 	"syscall"
     26 )
     27 
     28 // Error records the name of a binary that failed to be executed
     29 // and the reason it failed.
     30 type Error struct {
     31 	Name string
     32 	Err  error
     33 }
     34 
     35 func (e *Error) Error() string {
     36 	return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error()
     37 }
     38 
     39 // Cmd represents an external command being prepared or run.
     40 //
     41 // A Cmd cannot be reused after calling its Run, Output or CombinedOutput
     42 // methods.
     43 type Cmd struct {
     44 	// Path is the path of the command to run.
     45 	//
     46 	// This is the only field that must be set to a non-zero
     47 	// value. If Path is relative, it is evaluated relative
     48 	// to Dir.
     49 	Path string
     50 
     51 	// Args holds command line arguments, including the command as Args[0].
     52 	// If the Args field is empty or nil, Run uses {Path}.
     53 	//
     54 	// In typical use, both Path and Args are set by calling Command.
     55 	Args []string
     56 
     57 	// Env specifies the environment of the process.
     58 	// If Env is nil, Run uses the current process's environment.
     59 	Env []string
     60 
     61 	// Dir specifies the working directory of the command.
     62 	// If Dir is the empty string, Run runs the command in the
     63 	// calling process's current directory.
     64 	Dir string
     65 
     66 	// Stdin specifies the process's standard input.
     67 	// If Stdin is nil, the process reads from the null device (os.DevNull).
     68 	// If Stdin is an *os.File, the process's standard input is connected
     69 	// directly to that file.
     70 	// Otherwise, during the execution of the command a separate
     71 	// goroutine reads from Stdin and delivers that data to the command
     72 	// over a pipe. In this case, Wait does not complete until the goroutine
     73 	// stops copying, either because it has reached the end of Stdin
     74 	// (EOF or a read error) or because writing to the pipe returned an error.
     75 	Stdin io.Reader
     76 
     77 	// Stdout and Stderr specify the process's standard output and error.
     78 	//
     79 	// If either is nil, Run connects the corresponding file descriptor
     80 	// to the null device (os.DevNull).
     81 	//
     82 	// If Stdout and Stderr are the same writer, at most one
     83 	// goroutine at a time will call Write.
     84 	Stdout io.Writer
     85 	Stderr io.Writer
     86 
     87 	// ExtraFiles specifies additional open files to be inherited by the
     88 	// new process. It does not include standard input, standard output, or
     89 	// standard error. If non-nil, entry i becomes file descriptor 3+i.
     90 	//
     91 	// BUG(rsc): On OS X 10.6, child processes may sometimes inherit unwanted fds.
     92 	// https://golang.org/issue/2603
     93 	ExtraFiles []*os.File
     94 
     95 	// SysProcAttr holds optional, operating system-specific attributes.
     96 	// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
     97 	SysProcAttr *syscall.SysProcAttr
     98 
     99 	// Process is the underlying process, once started.
    100 	Process *os.Process
    101 
    102 	// ProcessState contains information about an exited process,
    103 	// available after a call to Wait or Run.
    104 	ProcessState *os.ProcessState
    105 
    106 	ctx             context.Context // nil means none
    107 	lookPathErr     error           // LookPath error, if any.
    108 	finished        bool            // when Wait was called
    109 	childFiles      []*os.File
    110 	closeAfterStart []io.Closer
    111 	closeAfterWait  []io.Closer
    112 	goroutine       []func() error
    113 	errch           chan error // one send per goroutine
    114 	waitDone        chan struct{}
    115 }
    116 
    117 // Command returns the Cmd struct to execute the named program with
    118 // the given arguments.
    119 //
    120 // It sets only the Path and Args in the returned structure.
    121 //
    122 // If name contains no path separators, Command uses LookPath to
    123 // resolve name to a complete path if possible. Otherwise it uses name
    124 // directly as Path.
    125 //
    126 // The returned Cmd's Args field is constructed from the command name
    127 // followed by the elements of arg, so arg should not include the
    128 // command name itself. For example, Command("echo", "hello").
    129 // Args[0] is always name, not the possibly resolved Path.
    130 func Command(name string, arg ...string) *Cmd {
    131 	cmd := &Cmd{
    132 		Path: name,
    133 		Args: append([]string{name}, arg...),
    134 	}
    135 	if filepath.Base(name) == name {
    136 		if lp, err := LookPath(name); err != nil {
    137 			cmd.lookPathErr = err
    138 		} else {
    139 			cmd.Path = lp
    140 		}
    141 	}
    142 	return cmd
    143 }
    144 
    145 // CommandContext is like Command but includes a context.
    146 //
    147 // The provided context is used to kill the process (by calling
    148 // os.Process.Kill) if the context becomes done before the command
    149 // completes on its own.
    150 func CommandContext(ctx context.Context, name string, arg ...string) *Cmd {
    151 	if ctx == nil {
    152 		panic("nil Context")
    153 	}
    154 	cmd := Command(name, arg...)
    155 	cmd.ctx = ctx
    156 	return cmd
    157 }
    158 
    159 // interfaceEqual protects against panics from doing equality tests on
    160 // two interfaces with non-comparable underlying types.
    161 func interfaceEqual(a, b interface{}) bool {
    162 	defer func() {
    163 		recover()
    164 	}()
    165 	return a == b
    166 }
    167 
    168 func (c *Cmd) envv() []string {
    169 	if c.Env != nil {
    170 		return c.Env
    171 	}
    172 	return os.Environ()
    173 }
    174 
    175 func (c *Cmd) argv() []string {
    176 	if len(c.Args) > 0 {
    177 		return c.Args
    178 	}
    179 	return []string{c.Path}
    180 }
    181 
    182 // skipStdinCopyError optionally specifies a function which reports
    183 // whether the provided the stdin copy error should be ignored.
    184 // It is non-nil everywhere but Plan 9, which lacks EPIPE. See exec_posix.go.
    185 var skipStdinCopyError func(error) bool
    186 
    187 func (c *Cmd) stdin() (f *os.File, err error) {
    188 	if c.Stdin == nil {
    189 		f, err = os.Open(os.DevNull)
    190 		if err != nil {
    191 			return
    192 		}
    193 		c.closeAfterStart = append(c.closeAfterStart, f)
    194 		return
    195 	}
    196 
    197 	if f, ok := c.Stdin.(*os.File); ok {
    198 		return f, nil
    199 	}
    200 
    201 	pr, pw, err := os.Pipe()
    202 	if err != nil {
    203 		return
    204 	}
    205 
    206 	c.closeAfterStart = append(c.closeAfterStart, pr)
    207 	c.closeAfterWait = append(c.closeAfterWait, pw)
    208 	c.goroutine = append(c.goroutine, func() error {
    209 		_, err := io.Copy(pw, c.Stdin)
    210 		if skip := skipStdinCopyError; skip != nil && skip(err) {
    211 			err = nil
    212 		}
    213 		if err1 := pw.Close(); err == nil {
    214 			err = err1
    215 		}
    216 		return err
    217 	})
    218 	return pr, nil
    219 }
    220 
    221 func (c *Cmd) stdout() (f *os.File, err error) {
    222 	return c.writerDescriptor(c.Stdout)
    223 }
    224 
    225 func (c *Cmd) stderr() (f *os.File, err error) {
    226 	if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
    227 		return c.childFiles[1], nil
    228 	}
    229 	return c.writerDescriptor(c.Stderr)
    230 }
    231 
    232 func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) {
    233 	if w == nil {
    234 		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
    235 		if err != nil {
    236 			return
    237 		}
    238 		c.closeAfterStart = append(c.closeAfterStart, f)
    239 		return
    240 	}
    241 
    242 	if f, ok := w.(*os.File); ok {
    243 		return f, nil
    244 	}
    245 
    246 	pr, pw, err := os.Pipe()
    247 	if err != nil {
    248 		return
    249 	}
    250 
    251 	c.closeAfterStart = append(c.closeAfterStart, pw)
    252 	c.closeAfterWait = append(c.closeAfterWait, pr)
    253 	c.goroutine = append(c.goroutine, func() error {
    254 		_, err := io.Copy(w, pr)
    255 		pr.Close() // in case io.Copy stopped due to write error
    256 		return err
    257 	})
    258 	return pw, nil
    259 }
    260 
    261 func (c *Cmd) closeDescriptors(closers []io.Closer) {
    262 	for _, fd := range closers {
    263 		fd.Close()
    264 	}
    265 }
    266 
    267 // Run starts the specified command and waits for it to complete.
    268 //
    269 // The returned error is nil if the command runs, has no problems
    270 // copying stdin, stdout, and stderr, and exits with a zero exit
    271 // status.
    272 //
    273 // If the command fails to run or doesn't complete successfully, the
    274 // error is of type *ExitError. Other error types may be
    275 // returned for I/O problems.
    276 func (c *Cmd) Run() error {
    277 	if err := c.Start(); err != nil {
    278 		return err
    279 	}
    280 	return c.Wait()
    281 }
    282 
    283 // lookExtensions finds windows executable by its dir and path.
    284 // It uses LookPath to try appropriate extensions.
    285 // lookExtensions does not search PATH, instead it converts `prog` into `.\prog`.
    286 func lookExtensions(path, dir string) (string, error) {
    287 	if filepath.Base(path) == path {
    288 		path = filepath.Join(".", path)
    289 	}
    290 	if dir == "" {
    291 		return LookPath(path)
    292 	}
    293 	if filepath.VolumeName(path) != "" {
    294 		return LookPath(path)
    295 	}
    296 	if len(path) > 1 && os.IsPathSeparator(path[0]) {
    297 		return LookPath(path)
    298 	}
    299 	dirandpath := filepath.Join(dir, path)
    300 	// We assume that LookPath will only add file extension.
    301 	lp, err := LookPath(dirandpath)
    302 	if err != nil {
    303 		return "", err
    304 	}
    305 	ext := strings.TrimPrefix(lp, dirandpath)
    306 	return path + ext, nil
    307 }
    308 
    309 // Start starts the specified command but does not wait for it to complete.
    310 //
    311 // The Wait method will return the exit code and release associated resources
    312 // once the command exits.
    313 func (c *Cmd) Start() error {
    314 	if c.lookPathErr != nil {
    315 		c.closeDescriptors(c.closeAfterStart)
    316 		c.closeDescriptors(c.closeAfterWait)
    317 		return c.lookPathErr
    318 	}
    319 	if runtime.GOOS == "windows" {
    320 		lp, err := lookExtensions(c.Path, c.Dir)
    321 		if err != nil {
    322 			c.closeDescriptors(c.closeAfterStart)
    323 			c.closeDescriptors(c.closeAfterWait)
    324 			return err
    325 		}
    326 		c.Path = lp
    327 	}
    328 	if c.Process != nil {
    329 		return errors.New("exec: already started")
    330 	}
    331 	if c.ctx != nil {
    332 		select {
    333 		case <-c.ctx.Done():
    334 			c.closeDescriptors(c.closeAfterStart)
    335 			c.closeDescriptors(c.closeAfterWait)
    336 			return c.ctx.Err()
    337 		default:
    338 		}
    339 	}
    340 
    341 	type F func(*Cmd) (*os.File, error)
    342 	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
    343 		fd, err := setupFd(c)
    344 		if err != nil {
    345 			c.closeDescriptors(c.closeAfterStart)
    346 			c.closeDescriptors(c.closeAfterWait)
    347 			return err
    348 		}
    349 		c.childFiles = append(c.childFiles, fd)
    350 	}
    351 	c.childFiles = append(c.childFiles, c.ExtraFiles...)
    352 
    353 	var err error
    354 	c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
    355 		Dir:   c.Dir,
    356 		Files: c.childFiles,
    357 		Env:   c.envv(),
    358 		Sys:   c.SysProcAttr,
    359 	})
    360 	if err != nil {
    361 		c.closeDescriptors(c.closeAfterStart)
    362 		c.closeDescriptors(c.closeAfterWait)
    363 		return err
    364 	}
    365 
    366 	c.closeDescriptors(c.closeAfterStart)
    367 
    368 	c.errch = make(chan error, len(c.goroutine))
    369 	for _, fn := range c.goroutine {
    370 		go func(fn func() error) {
    371 			c.errch <- fn()
    372 		}(fn)
    373 	}
    374 
    375 	if c.ctx != nil {
    376 		c.waitDone = make(chan struct{})
    377 		go func() {
    378 			select {
    379 			case <-c.ctx.Done():
    380 				c.Process.Kill()
    381 			case <-c.waitDone:
    382 			}
    383 		}()
    384 	}
    385 
    386 	return nil
    387 }
    388 
    389 // An ExitError reports an unsuccessful exit by a command.
    390 type ExitError struct {
    391 	*os.ProcessState
    392 
    393 	// Stderr holds a subset of the standard error output from the
    394 	// Cmd.Output method if standard error was not otherwise being
    395 	// collected.
    396 	//
    397 	// If the error output is long, Stderr may contain only a prefix
    398 	// and suffix of the output, with the middle replaced with
    399 	// text about the number of omitted bytes.
    400 	//
    401 	// Stderr is provided for debugging, for inclusion in error messages.
    402 	// Users with other needs should redirect Cmd.Stderr as needed.
    403 	Stderr []byte
    404 }
    405 
    406 func (e *ExitError) Error() string {
    407 	return e.ProcessState.String()
    408 }
    409 
    410 // Wait waits for the command to exit.
    411 // It must have been started by Start.
    412 //
    413 // The returned error is nil if the command runs, has no problems
    414 // copying stdin, stdout, and stderr, and exits with a zero exit
    415 // status.
    416 //
    417 // If the command fails to run or doesn't complete successfully, the
    418 // error is of type *ExitError. Other error types may be
    419 // returned for I/O problems.
    420 //
    421 // If c.Stdin is not an *os.File, Wait also waits for the I/O loop
    422 // copying from c.Stdin into the process's standard input
    423 // to complete.
    424 //
    425 // Wait releases any resources associated with the Cmd.
    426 func (c *Cmd) Wait() error {
    427 	if c.Process == nil {
    428 		return errors.New("exec: not started")
    429 	}
    430 	if c.finished {
    431 		return errors.New("exec: Wait was already called")
    432 	}
    433 	c.finished = true
    434 
    435 	state, err := c.Process.Wait()
    436 	if c.waitDone != nil {
    437 		close(c.waitDone)
    438 	}
    439 	c.ProcessState = state
    440 
    441 	var copyError error
    442 	for range c.goroutine {
    443 		if err := <-c.errch; err != nil && copyError == nil {
    444 			copyError = err
    445 		}
    446 	}
    447 
    448 	c.closeDescriptors(c.closeAfterWait)
    449 
    450 	if err != nil {
    451 		return err
    452 	} else if !state.Success() {
    453 		return &ExitError{ProcessState: state}
    454 	}
    455 
    456 	return copyError
    457 }
    458 
    459 // Output runs the command and returns its standard output.
    460 // Any returned error will usually be of type *ExitError.
    461 // If c.Stderr was nil, Output populates ExitError.Stderr.
    462 func (c *Cmd) Output() ([]byte, error) {
    463 	if c.Stdout != nil {
    464 		return nil, errors.New("exec: Stdout already set")
    465 	}
    466 	var stdout bytes.Buffer
    467 	c.Stdout = &stdout
    468 
    469 	captureErr := c.Stderr == nil
    470 	if captureErr {
    471 		c.Stderr = &prefixSuffixSaver{N: 32 << 10}
    472 	}
    473 
    474 	err := c.Run()
    475 	if err != nil && captureErr {
    476 		if ee, ok := err.(*ExitError); ok {
    477 			ee.Stderr = c.Stderr.(*prefixSuffixSaver).Bytes()
    478 		}
    479 	}
    480 	return stdout.Bytes(), err
    481 }
    482 
    483 // CombinedOutput runs the command and returns its combined standard
    484 // output and standard error.
    485 func (c *Cmd) CombinedOutput() ([]byte, error) {
    486 	if c.Stdout != nil {
    487 		return nil, errors.New("exec: Stdout already set")
    488 	}
    489 	if c.Stderr != nil {
    490 		return nil, errors.New("exec: Stderr already set")
    491 	}
    492 	var b bytes.Buffer
    493 	c.Stdout = &b
    494 	c.Stderr = &b
    495 	err := c.Run()
    496 	return b.Bytes(), err
    497 }
    498 
    499 // StdinPipe returns a pipe that will be connected to the command's
    500 // standard input when the command starts.
    501 // The pipe will be closed automatically after Wait sees the command exit.
    502 // A caller need only call Close to force the pipe to close sooner.
    503 // For example, if the command being run will not exit until standard input
    504 // is closed, the caller must close the pipe.
    505 func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
    506 	if c.Stdin != nil {
    507 		return nil, errors.New("exec: Stdin already set")
    508 	}
    509 	if c.Process != nil {
    510 		return nil, errors.New("exec: StdinPipe after process started")
    511 	}
    512 	pr, pw, err := os.Pipe()
    513 	if err != nil {
    514 		return nil, err
    515 	}
    516 	c.Stdin = pr
    517 	c.closeAfterStart = append(c.closeAfterStart, pr)
    518 	wc := &closeOnce{File: pw}
    519 	c.closeAfterWait = append(c.closeAfterWait, closerFunc(wc.safeClose))
    520 	return wc, nil
    521 }
    522 
    523 type closeOnce struct {
    524 	*os.File
    525 
    526 	writers sync.RWMutex // coordinate safeClose and Write
    527 	once    sync.Once
    528 	err     error
    529 }
    530 
    531 func (c *closeOnce) Close() error {
    532 	c.once.Do(c.close)
    533 	return c.err
    534 }
    535 
    536 func (c *closeOnce) close() {
    537 	c.err = c.File.Close()
    538 }
    539 
    540 type closerFunc func() error
    541 
    542 func (f closerFunc) Close() error { return f() }
    543 
    544 // safeClose closes c being careful not to race with any calls to c.Write.
    545 // See golang.org/issue/9307 and TestEchoFileRace in exec_test.go.
    546 // In theory other calls could also be excluded (by writing appropriate
    547 // wrappers like c.Write's implementation below), but since c is most
    548 // commonly used as a WriteCloser, Write is the main one to worry about.
    549 // See also #7970, for which this is a partial fix for this specific instance.
    550 // The idea is that we return a WriteCloser, and so the caller can be
    551 // relied upon not to call Write and Close simultaneously, but it's less
    552 // obvious that cmd.Wait calls Close and that the caller must not call
    553 // Write and cmd.Wait simultaneously. In fact that seems too onerous.
    554 // So we change the use of Close in cmd.Wait to use safeClose, which will
    555 // synchronize with any Write.
    556 //
    557 // It's important that we know this won't block forever waiting for the
    558 // operations being excluded. At the point where this is called,
    559 // the invoked command has exited and the parent copy of the read side
    560 // of the pipe has also been closed, so there should really be no read side
    561 // of the pipe left. Any active writes should return very shortly with an EPIPE,
    562 // making it reasonable to wait for them.
    563 // Technically it is possible that the child forked a sub-process or otherwise
    564 // handed off the read side of the pipe before exiting and the current holder
    565 // is not reading from the pipe, and the pipe is full, in which case the close here
    566 // might block waiting for the write to complete. That's probably OK.
    567 // It's a small enough problem to be outweighed by eliminating the race here.
    568 func (c *closeOnce) safeClose() error {
    569 	c.writers.Lock()
    570 	err := c.Close()
    571 	c.writers.Unlock()
    572 	return err
    573 }
    574 
    575 func (c *closeOnce) Write(b []byte) (int, error) {
    576 	c.writers.RLock()
    577 	n, err := c.File.Write(b)
    578 	c.writers.RUnlock()
    579 	return n, err
    580 }
    581 
    582 func (c *closeOnce) WriteString(s string) (int, error) {
    583 	c.writers.RLock()
    584 	n, err := c.File.WriteString(s)
    585 	c.writers.RUnlock()
    586 	return n, err
    587 }
    588 
    589 // StdoutPipe returns a pipe that will be connected to the command's
    590 // standard output when the command starts.
    591 //
    592 // Wait will close the pipe after seeing the command exit, so most callers
    593 // need not close the pipe themselves; however, an implication is that
    594 // it is incorrect to call Wait before all reads from the pipe have completed.
    595 // For the same reason, it is incorrect to call Run when using StdoutPipe.
    596 // See the example for idiomatic usage.
    597 func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
    598 	if c.Stdout != nil {
    599 		return nil, errors.New("exec: Stdout already set")
    600 	}
    601 	if c.Process != nil {
    602 		return nil, errors.New("exec: StdoutPipe after process started")
    603 	}
    604 	pr, pw, err := os.Pipe()
    605 	if err != nil {
    606 		return nil, err
    607 	}
    608 	c.Stdout = pw
    609 	c.closeAfterStart = append(c.closeAfterStart, pw)
    610 	c.closeAfterWait = append(c.closeAfterWait, pr)
    611 	return pr, nil
    612 }
    613 
    614 // StderrPipe returns a pipe that will be connected to the command's
    615 // standard error when the command starts.
    616 //
    617 // Wait will close the pipe after seeing the command exit, so most callers
    618 // need not close the pipe themselves; however, an implication is that
    619 // it is incorrect to call Wait before all reads from the pipe have completed.
    620 // For the same reason, it is incorrect to use Run when using StderrPipe.
    621 // See the StdoutPipe example for idiomatic usage.
    622 func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
    623 	if c.Stderr != nil {
    624 		return nil, errors.New("exec: Stderr already set")
    625 	}
    626 	if c.Process != nil {
    627 		return nil, errors.New("exec: StderrPipe after process started")
    628 	}
    629 	pr, pw, err := os.Pipe()
    630 	if err != nil {
    631 		return nil, err
    632 	}
    633 	c.Stderr = pw
    634 	c.closeAfterStart = append(c.closeAfterStart, pw)
    635 	c.closeAfterWait = append(c.closeAfterWait, pr)
    636 	return pr, nil
    637 }
    638 
    639 // prefixSuffixSaver is an io.Writer which retains the first N bytes
    640 // and the last N bytes written to it. The Bytes() methods reconstructs
    641 // it with a pretty error message.
    642 type prefixSuffixSaver struct {
    643 	N         int // max size of prefix or suffix
    644 	prefix    []byte
    645 	suffix    []byte // ring buffer once len(suffix) == N
    646 	suffixOff int    // offset to write into suffix
    647 	skipped   int64
    648 
    649 	// TODO(bradfitz): we could keep one large []byte and use part of it for
    650 	// the prefix, reserve space for the '... Omitting N bytes ...' message,
    651 	// then the ring buffer suffix, and just rearrange the ring buffer
    652 	// suffix when Bytes() is called, but it doesn't seem worth it for
    653 	// now just for error messages. It's only ~64KB anyway.
    654 }
    655 
    656 func (w *prefixSuffixSaver) Write(p []byte) (n int, err error) {
    657 	lenp := len(p)
    658 	p = w.fill(&w.prefix, p)
    659 
    660 	// Only keep the last w.N bytes of suffix data.
    661 	if overage := len(p) - w.N; overage > 0 {
    662 		p = p[overage:]
    663 		w.skipped += int64(overage)
    664 	}
    665 	p = w.fill(&w.suffix, p)
    666 
    667 	// w.suffix is full now if p is non-empty. Overwrite it in a circle.
    668 	for len(p) > 0 { // 0, 1, or 2 iterations.
    669 		n := copy(w.suffix[w.suffixOff:], p)
    670 		p = p[n:]
    671 		w.skipped += int64(n)
    672 		w.suffixOff += n
    673 		if w.suffixOff == w.N {
    674 			w.suffixOff = 0
    675 		}
    676 	}
    677 	return lenp, nil
    678 }
    679 
    680 // fill appends up to len(p) bytes of p to *dst, such that *dst does not
    681 // grow larger than w.N. It returns the un-appended suffix of p.
    682 func (w *prefixSuffixSaver) fill(dst *[]byte, p []byte) (pRemain []byte) {
    683 	if remain := w.N - len(*dst); remain > 0 {
    684 		add := minInt(len(p), remain)
    685 		*dst = append(*dst, p[:add]...)
    686 		p = p[add:]
    687 	}
    688 	return p
    689 }
    690 
    691 func (w *prefixSuffixSaver) Bytes() []byte {
    692 	if w.suffix == nil {
    693 		return w.prefix
    694 	}
    695 	if w.skipped == 0 {
    696 		return append(w.prefix, w.suffix...)
    697 	}
    698 	var buf bytes.Buffer
    699 	buf.Grow(len(w.prefix) + len(w.suffix) + 50)
    700 	buf.Write(w.prefix)
    701 	buf.WriteString("\n... omitting ")
    702 	buf.WriteString(strconv.FormatInt(w.skipped, 10))
    703 	buf.WriteString(" bytes ...\n")
    704 	buf.Write(w.suffix[w.suffixOff:])
    705 	buf.Write(w.suffix[:w.suffixOff])
    706 	return buf.Bytes()
    707 }
    708 
    709 func minInt(a, b int) int {
    710 	if a < b {
    711 		return a
    712 	}
    713 	return b
    714 }
    715