func SafeWriteToFile(t SafeWriter, mode os.FileMode) error {
	fn := t.GetFilename()
	G.Log.Debug(fmt.Sprintf("+ Writing to %s", fn))
	tmpfn, tmp, err := OpenTempFile(fn, "", mode)
	G.Log.Debug(fmt.Sprintf("| Temporary file generated: %s", tmpfn))
	if err != nil {
		return err
	}
	_, err = t.WriteTo(tmp)
	if err == nil {
		err = tmp.Close()
		if err == nil {
			err = os.Rename(tmpfn, fn)
		} else {
			G.Log.Error(fmt.Sprintf("Error closing temporary file %s: %s", tmpfn, err))
			os.Remove(tmpfn)
		}
	} else {
		G.Log.Error(fmt.Sprintf("Error writing temporary file %s: %s", tmpfn, err))
		tmp.Close()
		os.Remove(tmpfn)
	}
	G.Log.Debug(fmt.Sprintf("- Wrote to %s -> %s", fn, ErrToOk(err)))
	return err
}
SafeWriteToFile to safely write to a file. Use mode=0 for default permissions.
package libkb
import (
	"bufio"
	"bytes"
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base32"
	"encoding/hex"
	"fmt"
	"io"
	"math"
	"math/big"
	"os"
	"os/user"
	"path/filepath"
	"regexp"
	"strings"
	"time"
	"unicode"
	"github.com/keybase/client/go/logger"
	keybase1 "github.com/keybase/client/go/protocol"
)
var PrereleaseBuild string
func VersionString() string {
	if PrereleaseBuild != "" {
		return fmt.Sprintf("%s-%s", Version, PrereleaseBuild)
	}
	return Version
}
func ErrToOk(err error) string {
	if err == nil {
		return "ok"
	}
	return "ERROR: " + err.Error()
}
func FileExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
func MakeParentDirs(filename string) error {
	dir, _ := filepath.Split(filename)
	exists, err := FileExists(dir)
	if err != nil {
		G.Log.Errorf("Can't see if parent dir %s exists", dir)
		return err
	}
	if !exists {
		err = os.MkdirAll(dir, PermDir)
		if err != nil {
			G.Log.Errorf("Can't make parent dir %s", dir)
			return err
		}
		G.Log.Debug("Created parent directory %s", dir)
	}
	return nil
}
func FastByteArrayEq(a, b []byte) bool {
	return bytes.Equal(a, b)
}
func SecureByteArrayEq(a, b []byte) bool {
	return hmac.Equal(a, b)
}
func FormatTime(tm time.Time) string {
	layout := "2006-01-02 15:04:05 MST"
	return tm.Format(layout)
}
func Cicmp(s1, s2 string) bool {
	return strings.ToLower(s1) == strings.ToLower(s2)
}
func TrimCicmp(s1, s2 string) bool {
	return Cicmp(strings.TrimSpace(s1), strings.TrimSpace(s2))
}
func NameTrim(s string) string {
	s = strings.ToLower(strings.TrimSpace(s))
	strip := func(r rune) rune {
		switch {
		case r == '_', r == '-', r == '+', r == '\'':
			return -1
		case unicode.IsSpace(r):
			return -1
		}
		return r
	}
	return strings.Map(strip, s)
}
func NameCmp(n1, n2 string) bool {
	return NameTrim(n1) == NameTrim(n2)
}
func PickFirstError(errors ...error) error {
	for _, e := range errors {
		if e != nil {
			return e
		}
	}
	return nil
}
type FirstErrorPicker struct {
	e error
}
func (p *FirstErrorPicker) Push(e error) {
	if e != nil && p.e == nil {
		p.e = e
	}
}
func (p *FirstErrorPicker) Error() error {
	return p.e
}
func GiveMeAnS(i int) string {
	if i != 1 {
		return "s"
	}
	return ""
}
func KeybaseEmailAddress(s string) string {
	return s + "@keybase.io"
}
func DrainPipe(rc io.Reader, sink func(string)) error {
	scanner := bufio.NewScanner(rc)
	for scanner.Scan() {
		sink(scanner.Text())
	}
	return scanner.Err()
}
type SafeWriter interface {
	GetFilename() string
	WriteTo(io.Writer) (int64, error)
}