github.com/scaleoutsean/fusego@v0.0.0-20220224074057-4a6429e46bb8/mount.go (about)

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package fuse
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"os"
    21  )
    22  
    23  // Server is an interface for any type that knows how to serve ops read from a
    24  // connection.
    25  type Server interface {
    26  	// Read and serve ops from the supplied connection until EOF. Do not return
    27  	// until all operations have been responded to. Must not be called more than
    28  	// once.
    29  	ServeOps(*Connection)
    30  }
    31  
    32  // Mount attempts to mount a file system on the given directory, using the
    33  // supplied Server to serve connection requests. It blocks until the file
    34  // system is successfully mounted.
    35  func Mount(
    36  	dir string,
    37  	server Server,
    38  	config *MountConfig) (*MountedFileSystem, error) {
    39  	// Sanity check: make sure the mount point exists and is a directory. This
    40  	// saves us from some confusing errors later on OS X.
    41  	fi, err := os.Stat(dir)
    42  	switch {
    43  	case os.IsNotExist(err):
    44  		return nil, err
    45  
    46  	case err != nil:
    47  		return nil, fmt.Errorf("Statting mount point: %v", err)
    48  
    49  	case !fi.IsDir():
    50  		return nil, fmt.Errorf("Mount point %s is not a directory", dir)
    51  	}
    52  
    53  	// Initialize the struct.
    54  	mfs := &MountedFileSystem{
    55  		dir:                 dir,
    56  		joinStatusAvailable: make(chan struct{}),
    57  	}
    58  
    59  	// Begin the mounting process, which will continue in the background.
    60  	ready := make(chan error, 1)
    61  	dev, err := mount(dir, config, ready)
    62  	if err != nil {
    63  		return nil, fmt.Errorf("mount: %v", err)
    64  	}
    65  
    66  	// Choose a parent context for ops.
    67  	cfgCopy := *config
    68  	if cfgCopy.OpContext == nil {
    69  		cfgCopy.OpContext = context.Background()
    70  	}
    71  
    72  	// Create a Connection object wrapping the device.
    73  	connection, err := newConnection(
    74  		cfgCopy,
    75  		config.DebugLogger,
    76  		config.ErrorLogger,
    77  		dev)
    78  	if err != nil {
    79  		return nil, fmt.Errorf("newConnection: %v", err)
    80  	}
    81  
    82  	// Serve the connection in the background. When done, set the join status.
    83  	go func() {
    84  		server.ServeOps(connection)
    85  		mfs.joinStatus = connection.close()
    86  		close(mfs.joinStatusAvailable)
    87  	}()
    88  
    89  	// Wait for the mount process to complete.
    90  	if err := <-ready; err != nil {
    91  		return nil, fmt.Errorf("mount (background): %v", err)
    92  	}
    93  
    94  	return mfs, nil
    95  }