Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
352 lines
10 KiB
Go
352 lines
10 KiB
Go
//go:build darwin || freebsd || linux
|
|
|
|
package command
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"os/signal"
|
|
"strconv"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/glog"
|
|
"github.com/seaweedfs/seaweedfs/weed/util"
|
|
util_http "github.com/seaweedfs/seaweedfs/weed/util/http"
|
|
)
|
|
|
|
type parameter struct {
|
|
name string
|
|
value string
|
|
}
|
|
|
|
func runFuse(cmd *Command, args []string) bool {
|
|
rawArgs := strings.Join(args, " ")
|
|
rawArgsLen := len(rawArgs)
|
|
option := strings.Builder{}
|
|
options := []parameter{}
|
|
masterProcess := true
|
|
fusermountPath := ""
|
|
|
|
// first parameter
|
|
i := 0
|
|
for i = 0; i < rawArgsLen && rawArgs[i] != ' '; i++ {
|
|
option.WriteByte(rawArgs[i])
|
|
}
|
|
options = append(options, parameter{"arg0", option.String()})
|
|
option.Reset()
|
|
|
|
for i++; i < rawArgsLen; i++ {
|
|
|
|
// space separator check for filled option
|
|
if rawArgs[i] == ' ' {
|
|
if option.Len() > 0 {
|
|
options = append(options, parameter{option.String(), "true"})
|
|
option.Reset()
|
|
}
|
|
|
|
// dash separator read option until next space
|
|
} else if rawArgs[i] == '-' {
|
|
for i++; i < rawArgsLen && rawArgs[i] != ' '; i++ {
|
|
option.WriteByte(rawArgs[i])
|
|
}
|
|
// ignore "-o"
|
|
if option.String() != "o" {
|
|
options = append(options, parameter{option.String(), "true"})
|
|
}
|
|
option.Reset()
|
|
|
|
// equal separator start option with pending value
|
|
} else if rawArgs[i] == '=' {
|
|
name := option.String()
|
|
option.Reset()
|
|
|
|
for i++; i < rawArgsLen && rawArgs[i] != ',' && rawArgs[i] != ' '; i++ {
|
|
// double quote separator read option until next double quote
|
|
if rawArgs[i] == '"' {
|
|
for i++; i < rawArgsLen && rawArgs[i] != '"'; i++ {
|
|
option.WriteByte(rawArgs[i])
|
|
}
|
|
|
|
// single quote separator read option until next single quote
|
|
} else if rawArgs[i] == '\'' {
|
|
for i++; i < rawArgsLen && rawArgs[i] != '\''; i++ {
|
|
option.WriteByte(rawArgs[i])
|
|
}
|
|
|
|
// add chars before comma
|
|
} else if rawArgs[i] != ' ' {
|
|
option.WriteByte(rawArgs[i])
|
|
}
|
|
}
|
|
|
|
options = append(options, parameter{name, option.String()})
|
|
option.Reset()
|
|
|
|
// comma separator just read current option
|
|
} else if rawArgs[i] == ',' {
|
|
options = append(options, parameter{option.String(), "true"})
|
|
option.Reset()
|
|
|
|
// what is not a separator fill option buffer
|
|
} else {
|
|
option.WriteByte(rawArgs[i])
|
|
}
|
|
}
|
|
|
|
// get residual option data
|
|
if option.Len() > 0 {
|
|
// add value to pending option
|
|
options = append(options, parameter{option.String(), "true"})
|
|
option.Reset()
|
|
}
|
|
|
|
// scan each parameter
|
|
for i := 0; i < len(options); i++ {
|
|
parameter := options[i]
|
|
|
|
switch parameter.name {
|
|
case "child":
|
|
masterProcess = false
|
|
if parsed, err := strconv.ParseInt(parameter.value, 10, 64); err == nil {
|
|
if parsed > math.MaxInt || parsed <= 0 {
|
|
panic(fmt.Errorf("parent PID %d is invalid", parsed))
|
|
}
|
|
mountOptions.fuseCommandPid = int(parsed)
|
|
} else {
|
|
panic(fmt.Errorf("parent PID %s is invalid: %w", parameter.value, err))
|
|
}
|
|
case "arg0":
|
|
mountOptions.dir = ¶meter.value
|
|
case "filer":
|
|
mountOptions.filer = ¶meter.value
|
|
case "filer.path":
|
|
mountOptions.filerMountRootPath = ¶meter.value
|
|
case "volumeName":
|
|
mountOptions.volumeName = ¶meter.value
|
|
case "dirAutoCreate":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.dirAutoCreate = &parsed
|
|
} else {
|
|
panic(fmt.Errorf("dirAutoCreate: %s", err))
|
|
}
|
|
case "collection":
|
|
mountOptions.collection = ¶meter.value
|
|
case "replication":
|
|
mountOptions.replication = ¶meter.value
|
|
case "disk":
|
|
mountOptions.diskType = ¶meter.value
|
|
case "ttl":
|
|
if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
|
|
intValue := int(parsed)
|
|
mountOptions.ttlSec = &intValue
|
|
} else {
|
|
panic(fmt.Errorf("ttl: %s", err))
|
|
}
|
|
case "chunkSizeLimitMB":
|
|
if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
|
|
intValue := int(parsed)
|
|
mountOptions.chunkSizeLimitMB = &intValue
|
|
} else {
|
|
panic(fmt.Errorf("chunkSizeLimitMB: %s", err))
|
|
}
|
|
case "cacheMetaTtlSec":
|
|
if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
|
|
intValue := int(parsed)
|
|
mountOptions.cacheMetaTtlSec = &intValue
|
|
} else {
|
|
panic(fmt.Errorf("cacheMetaTtlSec: %s", err))
|
|
}
|
|
case "dirIdleEvictSec":
|
|
if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
|
|
intValue := int(parsed)
|
|
mountOptions.dirIdleEvictSec = &intValue
|
|
} else {
|
|
panic(fmt.Errorf("dirIdleEvictSec: %s", err))
|
|
}
|
|
case "concurrentWriters":
|
|
if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
|
|
intValue := int(parsed)
|
|
mountOptions.concurrentWriters = &intValue
|
|
} else {
|
|
panic(fmt.Errorf("concurrentWriters: %s", err))
|
|
}
|
|
case "concurrentReaders":
|
|
if parsed, err := strconv.ParseInt(parameter.value, 0, 32); err == nil {
|
|
intValue := int(parsed)
|
|
mountOptions.concurrentReaders = &intValue
|
|
} else {
|
|
panic(fmt.Errorf("concurrentReaders: %s", err))
|
|
}
|
|
case "cacheDir":
|
|
mountOptions.cacheDirForRead = ¶meter.value
|
|
case "cacheCapacityMB":
|
|
if parsed, err := strconv.ParseInt(parameter.value, 0, 64); err == nil {
|
|
mountOptions.cacheSizeMBForRead = &parsed
|
|
} else {
|
|
panic(fmt.Errorf("cacheCapacityMB: %s", err))
|
|
}
|
|
case "cacheDirWrite":
|
|
mountOptions.cacheDirForWrite = ¶meter.value
|
|
case "writeBufferSizeMB":
|
|
if parsed, err := strconv.ParseInt(parameter.value, 0, 64); err == nil {
|
|
mountOptions.writeBufferSizeMB = &parsed
|
|
} else {
|
|
panic(fmt.Errorf("writeBufferSizeMB: %s", err))
|
|
}
|
|
case "dataCenter":
|
|
mountOptions.dataCenter = ¶meter.value
|
|
case "allowOthers":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.allowOthers = &parsed
|
|
} else {
|
|
panic(fmt.Errorf("allowOthers: %s", err))
|
|
}
|
|
case "umask":
|
|
mountOptions.umaskString = ¶meter.value
|
|
case "nonempty":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.nonempty = &parsed
|
|
} else {
|
|
panic(fmt.Errorf("nonempty: %s", err))
|
|
}
|
|
case "volumeServerAccess":
|
|
mountOptions.volumeServerAccess = ¶meter.value
|
|
case "map.uid":
|
|
mountOptions.uidMap = ¶meter.value
|
|
case "map.gid":
|
|
mountOptions.gidMap = ¶meter.value
|
|
case "readOnly":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.readOnly = &parsed
|
|
} else {
|
|
panic(fmt.Errorf("readOnly: %s", err))
|
|
}
|
|
case "disableXAttr":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
|
|
mountOptions.disableXAttr = &parsed
|
|
} else {
|
|
panic(fmt.Errorf("disableXAttr: %s", err))
|
|
}
|
|
case "cpuprofile":
|
|
mountCpuProfile = ¶meter.value
|
|
case "memprofile":
|
|
mountMemProfile = ¶meter.value
|
|
case "readRetryTime":
|
|
if parsed, err := time.ParseDuration(parameter.value); err == nil {
|
|
mountReadRetryTime = &parsed
|
|
} else {
|
|
panic(fmt.Errorf("readRetryTime: %s", err))
|
|
}
|
|
case "fusermount.path":
|
|
fusermountPath = parameter.value
|
|
case "config_dir":
|
|
if err := util.ConfigurationFileDirectory.Set(parameter.value); err != nil {
|
|
panic(fmt.Errorf("config_dir %s: %w", parameter.value, err))
|
|
}
|
|
// FUSE performance options
|
|
case "writebackCache":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.writebackCache = &parsed
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "failed to parse 'writebackCache' value %q: %v\n", parameter.value, err)
|
|
return false
|
|
}
|
|
case "asyncDio":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.asyncDio = &parsed
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "failed to parse 'asyncDio' value %q: %v\n", parameter.value, err)
|
|
return false
|
|
}
|
|
case "cacheSymlink":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.cacheSymlink = &parsed
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "failed to parse 'cacheSymlink' value %q: %v\n", parameter.value, err)
|
|
return false
|
|
}
|
|
// macOS-specific FUSE options
|
|
case "sys.novncache":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.novncache = &parsed
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "failed to parse 'sys.novncache' value %q: %v\n", parameter.value, err)
|
|
return false
|
|
}
|
|
case "autofs":
|
|
if parsed, err := strconv.ParseBool(parameter.value); err == nil {
|
|
mountOptions.hasAutofs = &parsed
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "failed to parse 'autofs' value %q: %v\n", parameter.value, err)
|
|
return false
|
|
}
|
|
case "_netdev":
|
|
// _netdev is used for systemd/fstab parser to signify that this is a network mount but systemd
|
|
// mount sometimes can't strip them off. Meanwhile, fuse3 would refuse to run with _netdev, we
|
|
// strip them here if it fails to be stripped by the caller.
|
|
//(See https://github.com/seaweedfs/seaweedfs/wiki/fstab/948a70df5c0d9d2d27561b96de53bde07a29d2db)
|
|
glog.V(0).Infof("ignoring _netdev mount option")
|
|
default:
|
|
t := parameter.name
|
|
if parameter.value != "true" {
|
|
t = fmt.Sprintf("%s=%s", parameter.name, parameter.value)
|
|
}
|
|
mountOptions.extraOptions = append(mountOptions.extraOptions, t)
|
|
}
|
|
}
|
|
|
|
util_http.InitGlobalHttpClient()
|
|
|
|
// the master start the child, release it then finish himself
|
|
if masterProcess {
|
|
arg0, err := os.Executable()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// pass our PID to the child process
|
|
pid := os.Getpid()
|
|
argv := append(os.Args, "-o", "child="+strconv.Itoa(pid))
|
|
|
|
c := make(chan os.Signal, 1)
|
|
signal.Notify(c, syscall.SIGTERM)
|
|
|
|
attr := os.ProcAttr{}
|
|
attr.Env = os.Environ()
|
|
|
|
child, err := os.StartProcess(arg0, argv, &attr)
|
|
|
|
if err != nil {
|
|
panic(fmt.Errorf("master process can not start child process: %s", err))
|
|
}
|
|
|
|
err = child.Release()
|
|
|
|
if err != nil {
|
|
panic(fmt.Errorf("master process can not release child process: %s", err))
|
|
}
|
|
|
|
select {
|
|
case <-c:
|
|
return true
|
|
}
|
|
}
|
|
|
|
if fusermountPath != "" {
|
|
if err := os.Setenv("PATH", fusermountPath); err != nil {
|
|
panic(fmt.Errorf("setenv: %s", err))
|
|
}
|
|
} else if os.Getenv("PATH") == "" {
|
|
if err := os.Setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin"); err != nil {
|
|
panic(fmt.Errorf("setenv: %s", err))
|
|
}
|
|
}
|
|
|
|
// just call "weed mount" command
|
|
return runMount(cmdMount, []string{})
|
|
}
|