示例#1
0
// ??
func SniffClose(name string, sink io.WriteCloser, source io.Reader, eof func()) {
	sniffer := newSniffer(name)
	z1, z2 := make(chan struct{}), make(chan struct{})
	go func() {
		io.Copy(sniffer, source)
		sniffer.warn("SRC=>EVE⋅⋅SINK", "closing")
		sniffer.Close()
		close(z1)
	}()
	go func() {
		io.Copy(sink, sniffer)
		sniffer.warn("SRC⋅⋅EVE=>SINK", "closing")
		sink.Close()
		close(z2)
	}()
	go func() {
		<-z1
		sniffer.warn("SRC=>EVE⋅⋅SINK", "closed")
		<-z2
		sniffer.warn("SRC⋅⋅EVE=>SINK", "closed")
		if eof != nil {
			eof()
		}
	}()
}
示例#2
0
文件: link.go 项目: jpittis/toxiproxy
// Start the link with the specified toxics
func (link *ToxicLink) Start(name string, source io.Reader, dest io.WriteCloser) {
	go func() {
		bytes, err := io.Copy(link.input, source)
		if err != nil {
			logrus.WithFields(logrus.Fields{
				"name":     link.proxy.Name,
				"upstream": link.proxy.Upstream,
				"bytes":    bytes,
				"err":      err,
			}).Warn("Source terminated")
		}
		link.input.Close()
	}()
	for i, toxic := range link.toxics.chain {
		go link.stubs[i].Run(toxic)
	}
	go func() {
		bytes, err := io.Copy(dest, link.output)
		if err != nil {
			logrus.WithFields(logrus.Fields{
				"name":     link.proxy.Name,
				"upstream": link.proxy.Upstream,
				"bytes":    bytes,
				"err":      err,
			}).Warn("Destination terminated")
		}
		dest.Close()
		link.toxics.RemoveLink(name)
		link.proxy.RemoveConnection(name)
	}()
}
示例#3
0
func PGPKeyRawToArmored(raw []byte, priv bool) (ret string, err error) {

	var writer io.WriteCloser
	var out bytes.Buffer
	var which string

	if priv {
		which = "PRIVATE"
	} else {
		which = "PUBLIC"
	}
	hdr := fmt.Sprintf("PGP %s KEY BLOCK", which)

	writer, err = armor.Encode(&out, hdr, PGPArmorHeaders)

	if err != nil {
		return
	}
	if _, err = writer.Write(raw); err != nil {
		return
	}
	writer.Close()
	ret = out.String()
	return
}
示例#4
0
func saltpackSign(g *GlobalContext, source io.ReadCloser, sink io.WriteCloser, key NaclSigningKeyPair, streamer streamfn) error {
	defer func() {
		if err := source.Close(); err != nil {
			g.Log.Warning("error closing source: %s", err)
		}
		if err := sink.Close(); err != nil {
			g.Log.Warning("error closing sink: %s", err)
		}
	}()

	stream, err := streamer(sink, saltSigner{key}, KeybaseSaltpackBrand)
	if err != nil {
		return err
	}

	if _, err := io.Copy(stream, source); err != nil {
		return err
	}

	if err = stream.Close(); err != nil {
		return err
	}

	return nil
}
//Backup - method to execute backup
func (s *MysqlPlugin) Backup() (err error) {
	lo.G.Debug("Starting backup of mysql-tile")
	var writer io.WriteCloser
	var persistanceBackuper cfbackup.PersistanceBackup
	var mysqlUserName, mysqlPassword string
	var sshConfigs []command.SshConfig

	if sshConfigs, err = s.getSSHConfig(); err == nil {
		//take first node to execute backup on
		sshConfig := sshConfigs[0]
		if mysqlUserName, mysqlPassword, err = s.getMysqlCredentials(); err == nil {
			lo.G.Debug("Successfully got mysqlCredentials")
			if persistanceBackuper, err = s.GetPersistanceBackup(mysqlUserName, mysqlPassword, sshConfig); err == nil {
				if writer, err = s.PivotalCF.NewArchiveWriter(outputFileName); err == nil {
					defer writer.Close()
					lo.G.Debug("Starting mysql dump")
					err = persistanceBackuper.Dump(writer)
					lo.G.Debug("Dump finished", err)
				}
			}
		}
	}
	lo.G.Debug("Finished backup of mysql-tile", err)
	return
}
示例#6
0
func HandleWrite(ctx syncer.Context, l uri.Uri, r uri.Uri) error {
	if l.ModTime().Sub(r.ModTime()) < 0 {
		return ctx.Finish()
	}
	var (
		reader io.ReadCloser
		writer io.WriteCloser
		err    error
	)

	for {
		reader, err = l.OpenRead()
		if err == nil {
			break
		}
		time.Sleep(time.Second * 20)
	}
	for {
		writer, err = r.OpenWrite()
		if err == nil {
			break
		}
		time.Sleep(time.Minute * 10)
	}
	defer reader.Close()
	defer writer.Close()
	_, err = io.Copy(writer, reader)
	if err != nil {
		ctx.EmitLog(syncer.TypeError, err)
	}
	ctx.EmitLog(syncer.TypeInfo, "write to ", r.Uri())
	return err
}
示例#7
0
func migrateCommandFunc(cmd *cobra.Command, args []string) {
	var (
		writer io.WriteCloser
		reader io.ReadCloser
		errc   chan error
	)
	if migrateTransformer != "" {
		writer, reader, errc = startTransformer()
	} else {
		fmt.Println("using default transformer")
		writer, reader, errc = defaultTransformer()
	}

	st, index := rebuildStoreV2()
	be := prepareBackend()
	defer be.Close()

	go func() {
		writeStore(writer, st)
		writer.Close()
	}()

	readKeys(reader, be)
	mvcc.UpdateConsistentIndex(be, index)
	err := <-errc
	if err != nil {
		fmt.Println("failed to transform keys")
		ExitWithError(ExitError, err)
	}

	fmt.Println("finished transforming keys")
}
示例#8
0
func (cl *Client) readTransport(w io.WriteCloser) {
	defer w.Close()
	p := make([]byte, 1024)
	for {
		if cl.socket == nil {
			cl.waitForSocket()
		}
		cl.socket.SetReadDeadline(time.Now().Add(time.Second))
		nr, err := cl.socket.Read(p)
		if nr == 0 {
			if errno, ok := err.(*net.OpError); ok {
				if errno.Timeout() {
					continue
				}
			}
			Warn.Logf("read: %s", err)
			break
		}
		nw, err := w.Write(p[:nr])
		if nw < nr {
			Warn.Logf("read: %s", err)
			break
		}
	}
}
示例#9
0
// Runs the command in the container of the specified pod.
// Attaches the processes stdin, stdout, and stderr. Optionally uses a
// tty.
func (r *runtime) ExecInContainer(containerID kubecontainer.ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error {
	glog.V(4).Infof("Hyper: execing %s in container %s.", cmd, containerID.ID)

	args := append([]string{}, "exec", "-a", containerID.ID)
	args = append(args, cmd...)
	command := r.buildCommand(args...)

	p, err := kubecontainer.StartPty(command)
	if err != nil {
		return err
	}
	defer p.Close()

	// make sure to close the stdout stream
	defer stdout.Close()

	if stdin != nil {
		go io.Copy(p, stdin)
	}

	if stdout != nil {
		go io.Copy(stdout, p)
	}
	return command.Wait()
}
示例#10
0
文件: dump.go 项目: sstallion/go
func dump(args ...string) error {
	var w io.WriteCloser

	if len(args) == 0 {
		w = hex.Dumper(os.Stdout)
	} else {
		var err error

		w, err = os.Create(args[0])
		if err != nil {
			return err
		}
	}
	defer w.Close()

	d, err := openDevice()
	if err != nil {
		return err
	}
	defer d.Close()

	if dumpCount == 0 {
		dumpCount = eeprom.MaxBytes - dumpStart
	}
	data := make([]byte, dumpCount)
	if err := d.Read(uint16(dumpStart), data); err != nil {
		d.Reset()
		return err
	}
	_, err = w.Write(data)
	return err
}
示例#11
0
func fakeEngine(r io.Reader, w io.WriteCloser) {
	buf := bufio.NewReader(r)
	for {
		line, _, err := buf.ReadLine()
		if err != nil {
			return
		}
		switch field := tokenise(string(line)); field.next() {
		case "uci":
			for _, o := range optionTests {
				fmt.Fprintf(w, "option name %s type %s %s\n", o.name, o.typ, o.other)
			}
			fmt.Fprintln(w, "uciok")
		case "isready":
			fmt.Fprintln(w, "readyok")
		case "setoption":
			// ignore
		case "go":
			for _, i := range infoTests {
				fmt.Fprintln(w, i.line)
			}
		case "quit":
			w.Close()
			return
		}
	}
}
示例#12
0
func write(w io.WriteCloser) error {
	if _, err := io.Copy(w, strings.NewReader(poem)); err != nil {
		return err
	}

	return w.Close()
}
示例#13
0
文件: client.go 项目: cleblanc87/rack
func (c *Client) Stream(path string, headers map[string]string, in io.Reader, out io.WriteCloser) error {
	origin := fmt.Sprintf("https://%s", c.Host)
	endpoint := fmt.Sprintf("wss://%s%s", c.Host, path)

	config, err := websocket.NewConfig(endpoint, origin)

	if err != nil {
		return err
	}

	config.TlsConfig = &tls.Config{
		InsecureSkipVerify: true,
	}

	config.Header.Set("Version", c.Version)

	userpass := fmt.Sprintf("convox:%s", c.Password)
	userpass_encoded := base64.StdEncoding.EncodeToString([]byte(userpass))

	config.Header.Add("Authorization", fmt.Sprintf("Basic %s", userpass_encoded))

	for k, v := range headers {
		config.Header.Add(k, v)
	}

	config.TlsConfig = &tls.Config{
		InsecureSkipVerify: true,
	}

	var ws *websocket.Conn

	if proxy := os.Getenv("HTTPS_PROXY"); proxy != "" {
		ws, err = c.proxyWebsocket(config, proxy)
	} else {
		ws, err = websocket.DialConfig(config)
	}

	if err != nil {
		return err
	}

	defer ws.Close()

	var wg sync.WaitGroup

	if in != nil {
		go io.Copy(ws, in)
	}

	if out != nil {
		wg.Add(1)
		go copyAsync(out, ws, &wg)
	}

	wg.Wait()

	out.Close()

	return nil
}
示例#14
0
func (context *ElasticRuntime) readWriterArchive(dbInfo SystemDump, databaseDir string, action int) (err error) {
	filename := fmt.Sprintf(ER_BACKUP_FILE_FORMAT, dbInfo.Get(SD_COMPONENT))
	filepath := path.Join(databaseDir, filename)

	var pb PersistanceBackup

	if pb, err = dbInfo.GetPersistanceBackup(); err == nil {
		switch action {
		case IMPORT_ARCHIVE:
			lo.G.Debug("we are doing something here now")
			var backupReader io.ReadCloser
			if backupReader, err = context.Reader(filepath); err == nil {
				defer backupReader.Close()
				err = pb.Import(backupReader)
			}
		case EXPORT_ARCHIVE:
			lo.G.Info("Dumping database to file")
			var backupWriter io.WriteCloser
			if backupWriter, err = context.Writer(filepath); err == nil {
				defer backupWriter.Close()
				err = pb.Dump(backupWriter)
			}
		}
	}
	return
}
示例#15
0
文件: ssh.go 项目: Reejoshi/cli
func copyAndClose(wg *sync.WaitGroup, dest io.WriteCloser, src io.Reader) {
	_, _ = io.Copy(dest, src)
	_ = dest.Close()
	if wg != nil {
		wg.Done()
	}
}
示例#16
0
func encryptMail(e Envelope, keys openpgp.EntityList) (*bytes.Buffer, error) {
	var err error
	var contenttype string
	var buffer *bytes.Buffer
	var armored io.WriteCloser
	var crypter io.WriteCloser

	buffer = bytes.NewBuffer(nil)

	armored, err = armor.Encode(buffer, "PGP MESSAGE", nil)
	if err != nil {
		return buffer, err
	}

	crypter, err = openpgp.Encrypt(armored, keys, nil, nil, nil)
	if err != nil {
		return buffer, err
	}

	contenttype = e.Mail.Header.Get("Content-Type")
	if contenttype == "" {
		contenttype = "text/plain"
	}
	fmt.Fprintf(crypter, "Content-Type: %s\n\n", contenttype)

	io.Copy(crypter, e.Mail.Body)
	crypter.Close()
	armored.Close()

	return buffer, nil
}
示例#17
0
文件: docs.go 项目: jmcfarlane/apex
// Run command.
func run(c *cobra.Command, args []string) (err error) {
	var w io.WriteCloser = os.Stdin

	if isatty.IsTerminal(os.Stdout.Fd()) {
		cmd := exec.Command("less", "-R")
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		defer cmd.Wait()

		w, err = cmd.StdinPipe()
		if err != nil {
			return err
		}
		defer w.Close()

		if err := cmd.Start(); err != nil {
			return err
		}
	}

	if topic == "" {
		return wiki.Topics(w)
	}

	return wiki.Topic(topic, w)
}
示例#18
0
文件: invoke.go 项目: nikai3d/serf
// Sends data on stdin for a user event. The stdin simply contains the
// payload (if any) of the event.
func userEventStdin(logger *log.Logger, stdin io.WriteCloser, e *serf.UserEvent) {
	defer stdin.Close()
	if _, err := stdin.Write(e.Payload); err != nil {
		logger.Printf("[ERR] Error writing user event payload: %s", err)
		return
	}
}
示例#19
0
文件: tmx.go 项目: pikkpoiss/tmxgo
func (d *Data) SetTileGrid(grid DataTileGrid) (err error) {
	var (
		buf        bytes.Buffer
		b64Encoder io.WriteCloser
		zlibWriter *zlib.Writer
		gids       []uint32
		gridTile   DataTileGridTile
	)
	d.Encoding = "base64"
	d.Compression = "zlib"
	d.RawTiles = []DataTile{}
	gids = make([]uint32, grid.Width*grid.Height)
	for y := 0; y < grid.Height; y++ {
		for x := 0; x < grid.Width; x++ {
			gridTile = grid.Tiles[x][y]
			gids[grid.Width*y+x] = encodeGid(
				gridTile.Id,
				gridTile.FlipX,
				gridTile.FlipY,
				gridTile.FlipD)
		}
	}
	b64Encoder = base64.NewEncoder(base64.StdEncoding, &buf)
	zlibWriter = zlib.NewWriter(b64Encoder)
	if err = binary.Write(zlibWriter, binary.LittleEndian, gids); err != nil {
		return
	}
	zlibWriter.Close()
	b64Encoder.Close()
	d.RawContents = buf.String()
	return
}
示例#20
0
文件: ublog.go 项目: chinahbcq/speed
func (ul *UbLog) updateLogFile(f string) {
	var fd io.WriteCloser
	var ofd io.WriteCloser
	var err error

	fname := ul.logPath + "/" + ul.logName + f
	if checkFileExist(fname) {
		return
	}

	//fmt.Println("log not exist: ", fname)
	fd, err = os.OpenFile(fname, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if nil != err {
		//fmt.Println("open new log err: ", err)
		return
	}

	//fmt.Println("open new log: ", fd)

	switch f {
	case ".wf":
		ofd = ul.wfFd
		ul.wfFd = fd
	default:
		ofd = ul.fd
		ul.fd = fd
	}

	if nil != ofd {
		//fmt.Println("close old log: ", ofd)
		ofd.Close()
	}
}
func (this *PacketCodecZlib) Encode(writer io.Writer, util []byte, packet Packet) (err error) {
	buffer := new(bytes.Buffer)
	err = this.codec.Encode(buffer, util, packet)
	if err != nil {
		return
	}
	if raw, ok := packet.(PacketRaw); ok && raw.Raw() {
		_, err = buffer.WriteTo(writer)
	} else if buffer.Len() < this.threshold {
		err = WriteVarInt(writer, util, 0)
		if err != nil {
			return
		}
		_, err = buffer.WriteTo(writer)
	} else {
		err = WriteVarInt(writer, util, buffer.Len())
		if err != nil {
			return
		}
		var zlibWriter io.WriteCloser
		zlibWriter, err = zlib.NewWriterLevel(writer, this.level)
		if err != nil {
			return
		}
		_, err = buffer.WriteTo(zlibWriter)
		if err != nil {
			return
		}
		err = zlibWriter.Close()
	}
	return
}
示例#22
0
文件: modules.go 项目: rday/web
/**
Attempts to encode the response according to the client's Accept-Encoding
header. If there is an error, or if the encoding requests aren't supported
then the original content is returned.

Encoding type:
 * deflate (zlib stream)
 * gzip

This should be the last module loaded
*/
func EncodeResponse(ctx *Context, content interface{}) (interface{}, error) {
	var compressed bytes.Buffer
	var output io.WriteCloser

	if len(ctx.Request.Header["Accept-Encoding"]) > 0 {
		for _, opt := range ctx.Request.Header["Accept-Encoding"] {
			if strings.Index(opt, "gzip") >= 0 {
				output = gzip.NewWriter(&compressed)
				ctx.SetHeader("Content-Encoding", "gzip", true)
			} else if strings.Index(opt, "deflate") >= 0 {
				output = zlib.NewWriter(&compressed)
				ctx.SetHeader("Content-Encoding", "deflate", true)
			}
		}
	}

	if output != nil {
		_, err := output.Write(content.([]byte))
		if err != nil {
			ctx.Server.Logger.Printf("EncodeResponse write failed: %s", err)
			return content, &WebError{500, err.Error()}
		}
		err = output.Close()
		return compressed.Bytes(), nil
	}

	return content, nil
}
示例#23
0
// Send will package and send the email.
func (e *ToEmail) Send(msg interface{}) error {
	// extract the 'to' and 'from' and build the email body
	from, to, email, err := e.buildEmail(msg)
	if err != nil {
		return err
	}

	// set the 'from'
	if err = e.client.Mail(from); err != nil {
		return err
	}
	// set the 'to'
	if err = e.client.Rcpt(to); err != nil {
		return err
	}
	// get a handle of a writer for the message..
	var w io.WriteCloser
	if w, err = e.client.Data(); err != nil {
		return err
	}
	// ...and send the message body
	if _, err = w.Write(email); err != nil {
		return err
	}
	if err = w.Close(); err != nil {
		return err
	}

	return nil
}
示例#24
0
文件: dump.go 项目: delayk/redis-port
func (cmd *cmdDump) Main() {
	from, output := args.from, args.output
	if len(from) == 0 {
		log.Panic("invalid argument: from")
	}
	if len(output) == 0 {
		output = "/dev/stdout"
	}

	log.Infof("dump from '%s' to '%s'\n", from, output)

	var dumpto io.WriteCloser
	if output != "/dev/stdout" {
		dumpto = openWriteFile(output)
		defer dumpto.Close()
	} else {
		dumpto = os.Stdout
	}

	master, nsize := cmd.SendCmd(from, args.passwd)
	defer master.Close()

	log.Infof("rdb file = %d\n", nsize)

	reader := bufio.NewReaderSize(master, ReaderBufferSize)
	writer := bufio.NewWriterSize(dumpto, WriterBufferSize)

	cmd.DumpRDBFile(reader, writer, nsize)

	if !args.extra {
		return
	}

	cmd.DumpCommand(reader, writer, nsize)
}
示例#25
0
// RecordResponse writes response's status, headers and body.
func (r *APIB) RecordResponse(resp *http.Response, status, headers, body []byte, wc io.WriteCloser) (err error) {
	indent := strings.Repeat(" ", 12)

	// indent headers
	var headersS []string
	s := bufio.NewScanner(bytes.NewReader(headers))
	for s.Scan() {
		headersS = append(headersS, indent+s.Text())
	}
	if err = s.Err(); err != nil {
		return
	}

	// indent body
	var bodyS []string
	s = bufio.NewScanner(bytes.NewReader(body))
	for s.Scan() {
		bodyS = append(bodyS, indent+s.Text())
	}
	if err = s.Err(); err != nil {
		return
	}

	err = apibResponseTemplate.Execute(wc, map[string]interface{}{
		"StatusCode": resp.StatusCode,
		"Headers":    strings.Join(headersS, "\n"),
		"Body":       strings.Join(bodyS, "\n"),
	})
	if err == nil {
		err = wc.Close()
	}
	return
}
示例#26
0
// Encrypt the provided bytes for the provided encryption
// keys recipients. Returns the encrypted content bytes.
func Encrypt(d []byte, encryptionKeys *openpgp.EntityList) ([]byte, error) {
	var buffer *bytes.Buffer = &bytes.Buffer{}
	var armoredWriter io.WriteCloser
	var cipheredWriter io.WriteCloser
	var err error

	// Create an openpgp armored cipher writer pointing on our
	// buffer
	armoredWriter, err = armor.Encode(buffer, "PGP MESSAGE", nil)
	if err != nil {
		return nil, NewPgpError(ERR_ENCRYPTION_ENCODING, fmt.Sprintf("Can't make armor: %v", err))
	}

	// Create an encrypted writer using the provided encryption keys
	cipheredWriter, err = openpgp.Encrypt(armoredWriter, *encryptionKeys, nil, nil, nil)
	if err != nil {
		return nil, NewPgpError(ERR_ENCRYPTION_ENCRYPT, fmt.Sprintf("Error encrypting: %v", err))
	}

	// Write (encrypts on the fly) the provided bytes to
	// cipheredWriter
	_, err = cipheredWriter.Write(d)
	if err != nil {
		return nil, NewPgpError(ERR_ENCRYPTION_ENCRYPT, fmt.Sprintf("Error copying encrypted content: %v", err))
	}

	cipheredWriter.Close()
	armoredWriter.Close()

	return buffer.Bytes(), nil
}
示例#27
0
// Send will package and send the email.
func (e *ToEmail) send(from, to string, email []byte) error {
	var err error
	// set the 'from'
	if err = e.client.Mail(from); err != nil {
		return err
	}
	// set the 'to'
	if err = e.client.Rcpt(to); err != nil {
		return err
	}
	// get a handle of a writer for the message..
	var w io.WriteCloser
	if w, err = e.client.Data(); err != nil {
		return err
	}
	// ...and send the message body
	if _, err = w.Write(email); err != nil {
		return err
	}
	if err = w.Close(); err != nil {
		return err
	}

	return nil
}
示例#28
0
func writeFile(data io.ReadCloser, filename string) error {
	if *dryrun {
		return nil
	}
	defer data.Close()

	// Setup file for write
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	var out io.WriteCloser
	switch *compression {
	case "none":
		out = f
	case "gzip":
		out = gzip.NewWriter(f)
		defer out.Close()
	default:
		return fmt.Errorf("Can't compress to type %q, only %q\n", *compression, "gzip")
	}

	written, err := io.Copy(out, data)
	if err != nil {
		fmt.Printf("Error on copy of data from DVID to file: %v\n", err)
		os.Exit(1)
	}
	fmt.Printf("Wrote %d MB to %s\n", written/1000000, filename)
	return nil
}
// Checks for input and output flags:
// 	- If output is set:
// 		- Create a file as output location with ".tmp" suffix added
// 		- When process is finished:
// 			- If there are no errors, move temporary file to the output location
// 			- Else, remove temporary file
// 	- Else, use stdout
//
// 	- If input is set, use processLoc func
// 	- Else, pass process func Stdin
//
// 	- After processing - if err exists, write to Stderr
func main() {
	var (
		err       error
		input     io.ReadCloser
		output    io.WriteCloser
		i, o, tmp string = getFlagLocs()
	)

	if input, err = getInput(i); err != nil {
		stderr("", err)
	}

	if output, err = getOutput(o, tmp); err != nil {
		stderr("", err)
	}

	if err == nil {
		err = process(input, output)
	}

	input.Close()
	output.Close()

	handleOutput(err, o, tmp)
	reportErrors(err)
}
示例#30
0
文件: io.go 项目: felixbuenemann/goon
func inLoop(pipe io.WriteCloser, stdin io.Reader, done chan bool) {
	buf := make([]byte, 2)
	logger.Println("Entering stdin loop")
	done <- true
	for {
		bytes_read, read_err := io.ReadFull(stdin, buf)
		if read_err == io.EOF && bytes_read == 0 {
			break
		}
		fatal_if(read_err)

		length := read16_be(buf)
		logger.Printf("in: packet length = %v\n", length)
		if length == 0 {
			// this is how Porcelain signals EOF from Elixir
			break
		}

		bytes_written, write_err := io.CopyN(pipe, stdin, int64(length))
		logger.Printf("in: copied %v bytes\n", bytes_written)
		fatal_if(write_err)
	}
	pipe.Close()
	done <- true
}