/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
go/kbfs/libfuse/mounter.go
170 строк
5 KB
chrisnojima-zoom
Version 670 - clean2 (#29122)
08 июн 2026, 19:31
Не верифицирован
08 июн 2026, 19:31
1943197
Код
Авторство
О чём код?
// Copyright 2016 Keybase Inc. All rights reserved. // Use of this source code is governed by a BSD // license that can be found in the LICENSE file. // //go:build !windows package libfuse import ( "bytes" "errors" "fmt" "os" "os/exec" "path" "runtime" "strings" "bazil.org/fuse" "github.com/keybase/client/go/kbconst" "github.com/keybase/client/go/libkb" "github.com/keybase/client/go/logger" keybase1 "github.com/keybase/client/go/protocol/keybase1" ) type mounter struct { options StartOptions c *fuse.Conn log logger.Logger runMode kbconst.RunMode } // fuseMount tries to mount the mountpoint. // On a force mount then unmount, re-mount if unsuccessful func (m *mounter) Mount() (err error) { defer func() { if err != nil { msg := fmt.Sprintf("KBFS failed to FUSE mount at %s: %s", m.options.MountPoint, err) fmt.Println(msg) m.log.Warning(msg) } }() m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams) // Exit if we were successful or we are not a force mounting on error. // Otherwise, try unmounting and mounting again. if err == nil || !m.options.ForceMount { return err } // Mount failed, let's try to unmount and then try mounting again, even // if unmounting errors here. _ = m.Unmount() // In case we are on darwin, ask the installer to reinstall the mount dir // and try again as the last resort. This specifically fixes a situation // where /keybase gets created and owned by root after Keybase app is // started, and `kbfs` later fails to mount because of a permission error. m.reinstallMountDirIfPossible() m.c, err = fuseMountDir(m.options.MountPoint, m.options.PlatformParams) return err } func fuseMountDir(dir string, platformParams PlatformParams) (*fuse.Conn, error) { // Create mountdir directory on Linux. switch libkb.RuntimeGroup() { case keybase1.RuntimeGroup_LINUXLIKE: // Inherit permissions from containing directory and umask. err := os.MkdirAll(dir, os.ModeDir|os.ModePerm) if err != nil { return nil, err } default: } fi, err := os.Stat(dir) if err != nil { return nil, err } if !fi.IsDir() { return nil, errors.New("mount point is not a directory") } options, err := getPlatformSpecificMountOptions(dir, platformParams) if err != nil { return nil, err } c, err := fuse.Mount(dir, options...) if err != nil { err = translatePlatformSpecificError(err, platformParams) return nil, err } return c, nil } func isFusermountMountNotFoundError(output []byte, err error) bool { if err == nil { return false } return bytes.Contains(output, []byte("not found in /etc/mtab")) } func (m *mounter) Unmount() (err error) { m.log.Info("Unmounting") dir := m.options.MountPoint // Try normal unmount switch runtime.GOOS { case "darwin": // no ios _, err = exec.Command("/sbin/umount", dir).Output() //nolint:gosec // G204: System unmount command with dir path case "linux": fusermountOutput, fusermountErr := exec.Command("fusermount", "-u", dir).CombinedOutput() //nolint:gosec // G204: System unmount command with dir path // Only clean up mountdir on a clean unmount. if fusermountErr == nil { m.log.Info("Successfully unmounted") defer m.DeleteMountdirIfEmpty() } if fusermountErr != nil { // Ignore errors where the mount was never mounted in the first place if isFusermountMountNotFoundError(fusermountOutput, fusermountErr) { m.log.Info("Ignoring mount-not-found fusermount error") } else { returnErr := fmt.Errorf("fusermount unmount resulted in unknown error: output=%v; err=%s", fusermountOutput, fusermountErr) m.log.Warning(returnErr.Error()) err = returnErr } } default: err = fuse.Unmount(dir) } if err != nil && m.options.ForceMount { // Unmount failed, so let's try and force it. switch runtime.GOOS { case "darwin": // no ios _, err = exec.Command( //nolint:gosec // G204: System force unmount command with dir path "/usr/sbin/diskutil", "unmountDisk", "force", dir).Output() case "linux": // Lazy unmount; will unmount when KBFS is no longer in use. _, err = exec.Command("fusermount", "-u", "-z", dir).Output() //nolint:gosec // G204: System force unmount command with dir path default: err = errors.New("Forced unmount is not supported on this platform yet") } } if execErr, ok := err.(*exec.ExitError); ok && execErr.Stderr != nil { err = fmt.Errorf("%s (%s)", execErr, execErr.Stderr) } return } func (m *mounter) DeleteMountdirIfEmpty() { m.log.Info("Deleting mountdir") // os.Remove refuses to delete non-empty directories. err := os.Remove(m.options.MountPoint) if err != nil { m.log.Errorf("Unable to delete mountdir: %s", err) } } // volumeName returns the first word of the directory (base) name func volumeName(dir string) (string, error) { // nolint volName := path.Base(dir) if volName == "." || volName == "/" { err := fmt.Errorf("Bad volume name: %v", volName) return "", err } s := strings.Split(volName, " ") if len(s) == 0 { return "", fmt.Errorf("Bad volume name: %v", volName) } return s[0], nil }