github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/dokan/dokan.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package dokan
     6  
     7  import (
     8  	"github.com/keybase/client/go/kbfs/dokan/winacl"
     9  )
    10  
    11  // MountHandle holds a reference to a mounted filesystem.
    12  type MountHandle struct {
    13  	errChan chan error
    14  	// Dir is the path of this mount.
    15  	Dir string
    16  }
    17  
    18  // Mount mounts a FileSystem with the given Config.
    19  // Mount returns when the filesystem has been mounted or there is an error.
    20  func Mount(cfg *Config) (*MountHandle, error) {
    21  	err := loadDokanDLL(cfg)
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  	var ec = make(chan error, 2)
    26  	var slot = fsTableStore(cfg.FileSystem, ec)
    27  	flags := cfg.MountFlags
    28  	go func() {
    29  		ctx := allocCtx(slot)
    30  		defer ctx.Free()
    31  		ec <- ctx.Run(cfg.Path, flags)
    32  		close(ec)
    33  	}()
    34  	// This gets a send from either
    35  	// 1) DokanMain from ctx.Run returns an error before mount
    36  	// 2) After the filesystem is mounted from handling the Mounted callback.
    37  	// Thus either the filesystem was mounted ok or it was not mounted
    38  	// and an err is not nil. DokanMain does not return errors after the
    39  	// mount, but if such errors occured they can be catched by BlockTillDone.
    40  	err = <-ec
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	return &MountHandle{ec, cfg.Path}, nil
    45  }
    46  
    47  // Close unmounts the filesystem. Can be used to interrupt a
    48  // running filesystem - usually not needed if BlockTillDone
    49  // is used.
    50  func (m *MountHandle) Close() error {
    51  	return Unmount(m.Dir)
    52  }
    53  
    54  // BlockTillDone blocks till Dokan is done.
    55  func (m *MountHandle) BlockTillDone() error {
    56  	// Two cases:
    57  	// 1) Mount got send from Mounted hook (nil) and we wait for the ctx.Run case
    58  	// 2) Mount got send from Mount (which errored) and closed the channel
    59  	err := <-m.errChan
    60  	return err
    61  }
    62  
    63  // Unmount a drive mounted by Dokan.
    64  func Unmount(path string) error {
    65  	return unmount(path)
    66  }
    67  
    68  // Path converts the path to UTF-8 running in O(n).
    69  func (fi *FileInfo) Path() string {
    70  	return lpcwstrToString(fi.rawPath)
    71  }
    72  
    73  // IsDeleteOnClose should be checked from Cleanup.
    74  func (fi *FileInfo) IsDeleteOnClose() bool {
    75  	return fi.ptr.DeleteOnClose != 0
    76  }
    77  
    78  // IsRequestorUserSidEqualTo returns true if the argument is equal
    79  // to the sid of the user associated with the filesystem request.
    80  func (fi *FileInfo) IsRequestorUserSidEqualTo(sid *winacl.SID) bool {
    81  	return fi.isRequestorUserSidEqualTo(sid)
    82  }
    83  
    84  // NumberOfFileHandles returns the number of open file handles for
    85  // this filesystem.
    86  func (fi *FileInfo) NumberOfFileHandles() uint32 {
    87  	return fsTableGetFileCount(uint32(fi.ptr.DokanOptions.GlobalContext))
    88  }