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 }