// FilterTLFEarlyExitError decides whether an error received while // trying to create a TLF should result in showing the user an empty // folder (exitEarly == true), or not. func FilterTLFEarlyExitError(ctx context.Context, err error, log logger.Logger, name libkbfs.CanonicalTlfName) ( exitEarly bool, retErr error) { switch err := err.(type) { case nil: // No error. return false, nil case libkbfs.WriteAccessError: // No permission to create TLF, so pretend it's still // empty. // // In theory, we need to invalidate this once the TLF // is created, but in practice, the Linux kernel // doesn't cache readdir results, and probably not // OSXFUSE either. log.CDebugf(ctx, "No permission to write to %s, so pretending it's empty", name) return true, nil case libkbfs.MDServerErrorWriteAccess: // Same as above; cannot fallthrough in type switch log.CDebugf(ctx, "No permission to write to %s, so pretending it's empty", name) return true, nil default: // Some other error. return true, err } }
func tail(Log logger.Logger, filename string, numLines int) string { if filename == "" { return "" } f, err := os.Open(filename) if err != nil { Log.Warning("error opening log %q: %s", filename, err) return "" } b := rogReverse.NewScanner(f) b.Split(bufio.ScanLines) var lines []string for b.Scan() { lines = append(lines, b.Text()) if len(lines) == numLines { break } } for left, right := 0, len(lines)-1; left < right; left, right = left+1, right-1 { lines[left], lines[right] = lines[right], lines[left] } return strings.Join(lines, "\n") }
func NewUpdater(options keybase1.UpdateOptions, source sources.UpdateSource, config Config, log logger.Logger) *Updater { log.Debug("New updater with options: %#v", options) return &Updater{ options: options, source: source, config: config, log: log, } }
// ShowStatus shows status info for a service func ShowStatus(label string, log logger.Logger) error { service := NewService(label) service.SetLogger(log) status, err := service.LoadStatus() if err != nil { return err } if status != nil { log.Info("%s", status.Description()) } else { log.Info("No service found with label: %s", label) } return nil }
// WaitForServiceInfoFile tries to wait for a service info file, which should be // written on successful service startup. func WaitForServiceInfoFile(path string, label string, pid string, maxAttempts int, wait time.Duration, reason string, log logger.Logger) (*ServiceInfo, error) { if pid == "" { return nil, fmt.Errorf("No pid to wait for") } lookForServiceInfo := func() (*ServiceInfo, error) { if _, ferr := os.Stat(path); os.IsNotExist(ferr) { return nil, nil } dat, err := ioutil.ReadFile(path) if err != nil { return nil, err } var serviceInfo ServiceInfo err = json.Unmarshal(dat, &serviceInfo) if err != nil { return nil, err } // Make sure the info file is the pid we are waiting for, otherwise it is // still starting up. if pid != fmt.Sprintf("%d", serviceInfo.Pid) { return nil, nil } // PIDs match, the service has started up return &serviceInfo, nil } attempt := 1 serviceInfo, lookErr := lookForServiceInfo() for attempt < maxAttempts && serviceInfo == nil { attempt++ log.Debug("Waiting for service info file...") time.Sleep(wait) serviceInfo, lookErr = lookForServiceInfo() } // If no service info was found, let's return an error if serviceInfo == nil { if lookErr == nil { lookErr = fmt.Errorf("%s isn't running (expecting pid=%s)", label, pid) } return nil, lookErr } // We succeeded in finding service info log.Debug("Found service info: %#v", *serviceInfo) return serviceInfo, nil }
func ctxWithRandomID(ctx context.Context, tagKey interface{}, tagName string, log logger.Logger) context.Context { // Tag each request with a unique ID logTags := make(logger.CtxLogTags) logTags[tagKey] = tagName newCtx := logger.NewContextWithLogTags(ctx, logTags) id, err := MakeRandomRequestID() if err != nil { if log != nil { log.Warning("Couldn't generate a random request ID: %v", err) } } else { newCtx = context.WithValue(newCtx, tagKey, id) } return newCtx }
// NewContextWithOpID adds a unique ID to this context, identifying // a particular request. func NewContextWithOpID(ctx context.Context, log logger.Logger) context.Context { if runtime.GOOS == "darwin" { // Timeout operations before they hit the osxfuse time limit, // so we don't hose the entire mount. The timeout is 60 // seconds, but it looks like sometimes it tries multiple // attempts within that 60 seconds, so let's go a little under // 60/3 to be safe. ctx, _ = context.WithTimeout(ctx, 19*time.Second) } id, err := libkbfs.MakeRandomRequestID() if err != nil { log.Errorf("Couldn't make request ID: %v", err) return ctx } return context.WithValue(ctx, CtxIDKey, id) }
func (r *RemoteStatus) loop(ctx context.Context, log logger.Logger, config libkbfs.Config) { for { tctx, cancel := context.WithTimeout(ctx, 1*time.Second) st, ch, err := config.KBFSOps().Status(tctx) // No deferring inside loops, and no panics either here. cancel() if err != nil { log.Warning("KBFS Status failed: %v", err) } r.update(st) // Block on the channel or shutdown. select { case <-ctx.Done(): return case <-ch: } } }
func makeBlockServer(config Config, serverInMemory bool, serverRootDir, bserverAddr string, log logger.Logger) ( BlockServer, error) { if serverInMemory { // local in-memory block server return NewBlockServerMemory(config) } if len(serverRootDir) > 0 { // local persistent block server blockPath := filepath.Join(serverRootDir, "kbfs_block") return NewBlockServerLocal(config, blockPath) } if len(bserverAddr) == 0 { return nil, errors.New("Empty block server address") } log.Debug("Using remote bserver %s", bserverAddr) return NewBlockServerRemote(config, bserverAddr), nil }
// ShowServices outputs keybase service info. func ShowServices(filters []string, name string, log logger.Logger) (err error) { services, err := ListServices(filters) if err != nil { return } if len(services) > 0 { log.Info("%s %s:", name, libkb.Pluralize(len(services), "service", "services", false)) for _, service := range services { log.Info(service.StatusDescription()) } log.Info("") } else { log.Info("No %s services.\n", name) } return }
func checkSystemUser(log logger.Logger) { if isAdminUser, match, _ := libkb.IsSystemAdminUser(); isAdminUser { log.Errorf("Oops, you are trying to run as an admin user (%s). This isn't supported.", match) os.Exit(int(keybase1.ExitCode_NOTOK)) } }
func warnNonProd(log logger.Logger, e *libkb.Env) { mode := e.GetRunMode() if mode != libkb.ProductionRunMode { log.Warning("Running in %s mode", mode) } }
func FindPinentry(log logger.Logger) (string, error) { if !HasWindows() { return "", fmt.Errorf("Can't spawn gui window, not using pinentry") } bins := []string{ // If you install MacTools you'll wind up with this pinentry "/usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac", } extraPaths := []string{} log.Debug("+ FindPinentry()") cmds := []string{ "pinentry-gtk-2", "pinentry-qt4", "pinentry", } checkFull := func(s string) bool { log.Debug("| Check fullpath %s", s) found := (canExec(s) == nil) if found { log.Debug("- Found: %s", s) } return found } for _, b := range bins { if checkFull(b) { return b, nil } } path := os.Getenv("PATH") for _, c := range cmds { log.Debug("| Looking for %s in standard PATH %s", c, path) fullc, err := exec.LookPath(c) if err == nil { log.Debug("- Found %s", fullc) return fullc, nil } } for _, ep := range extraPaths { for _, c := range cmds { full := filepath.Join(ep, c) if checkFull(full) { return full, nil } } } log.Debug("- FindPinentry: none found") return "", fmt.Errorf("No pinentry found, checked a bunch of different places") }
func FindPinentry(log logger.Logger) (string, error) { // // If you install GPG you'll wind up with this pinentry // C:\Program Files (x86)\GNU\GnuPG\pinentry-gtk-2.exe // C:\Program Files (x86)\GNU\GnuPG\pinentry-qt4.exe // C:\Program Files (x86)\GNU\GnuPG\pinentry-w32.exe // C:\Program Files (x86)\GNU\GnuPG\pinentry.exe k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Wow6432Node\GNU\GnuPG`, registry.QUERY_VALUE) if err != nil { k, err = registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\GNU\GnuPG`, registry.QUERY_VALUE) } if err != nil { log.Debug("- FindPinentry: can't open registry") } defer k.Close() installDir, _, err := k.GetStringValue("Install Directory") if err != nil { log.Debug("- FindPinentry: can't get string from registry") } extraPaths := []string{} log.Debug("+ FindPinentry()") cmds := []string{ "pinentry-gtk-2.exe", "pinentry-qt4.exe", "pinentry-w32.exe", "pinentry.exe", } // First, look where the registry points for _, c := range cmds { full := filepath.Join(installDir, c) log.Debug("| (registry) Looking for %s", full) _, err := exec.LookPath(full) if err == nil { return full, nil } } // Look in program files, just in case extraPaths = append(extraPaths, os.Getenv("ProgramFiles")) extraPaths = append(extraPaths, os.Getenv("ProgramFiles(x86)")) for _, ep := range extraPaths { for _, c := range cmds { full := filepath.Join(ep, "GNU", "GnuPG", c) log.Debug("| Looking for %s", full) _, err := exec.LookPath(full) if err == nil { return full, nil } } } log.Debug("- FindPinentry: none found") return "", fmt.Errorf("No pinentry found, checked a bunch of different places") }
func Trace(log logger.Logger, msg string, f func() error) func() { log.Debug("+ %s", msg) return func() { log.Debug("- %s -> %s", msg, ErrToOk(f())) } }