github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/mounter/mounter_nix.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  //go:build !windows
     5  // +build !windows
     6  
     7  package mounter
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"os/exec"
    13  	"runtime"
    14  
    15  	"bazil.org/fuse"
    16  )
    17  
    18  // Unmount tries to unmount normally and then if force if unsuccessful.
    19  func Unmount(dir string, force bool, log Log) error {
    20  	if !force {
    21  		mounted, err := IsMounted(dir, log)
    22  		if err != nil {
    23  			return err
    24  		}
    25  		if !mounted {
    26  			return fmt.Errorf("Not mounted")
    27  		}
    28  	}
    29  
    30  	log.Info("Trying to unmount: %s", dir)
    31  	err := fuse.Unmount(dir)
    32  	if err != nil {
    33  		if !force {
    34  			return err
    35  		}
    36  		// Unmount failed and we want to force it.
    37  		log.Info("Unmount %s failed: %s; We will try to force it", dir, err)
    38  		err = ForceUnmount(dir, log)
    39  	}
    40  	return err
    41  }
    42  
    43  // ForceUnmount tries to forcibly unmount a directory
    44  func ForceUnmount(dir string, log Log) error {
    45  	switch runtime.GOOS {
    46  	case "darwin", "ios":
    47  		log.Info("Force unmounting with diskutil")
    48  		out, err := exec.Command("/usr/sbin/diskutil", "unmountDisk", "force", dir).CombinedOutput()
    49  		log.Debug("Output: %s", string(out))
    50  		return err
    51  	case "linux":
    52  		log.Info("Force unmounting with umount -l")
    53  		out, err := exec.Command("umount", "-l", dir).CombinedOutput()
    54  		log.Debug("Output: %s", string(out))
    55  		return err
    56  	default:
    57  		return errors.New("Forced unmount is not supported on this platform yet")
    58  	}
    59  }