|
|
package command
import ( "fmt" "os" "strconv" "strings" "time" )
func init() { cmdFuse.Run = runFuse // break init cycle
}
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 case "arg0": mountOptions.dir = ¶meter.value case "filer": mountOptions.filer = ¶meter.value case "filer.path": mountOptions.filerMountRootPath = ¶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 "concurrentWriters": i++ 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 "cacheDir": mountOptions.cacheDir = ¶meter.value case "cacheCapacityMB": if parsed, err := strconv.ParseInt(parameter.value, 0, 64); err == nil { mountOptions.cacheSizeMB = &parsed } else { panic(fmt.Errorf("cacheCapacityMB: %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 "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 default: t := parameter.name if parameter.value != "true" { t = fmt.Sprintf("%s=%s", parameter.name, parameter.value) } mountOptions.extraOptions = append(mountOptions.extraOptions, t) } }
// the master start the child, release it then finish himself
if masterProcess { arg0, err := os.Executable() if err != nil { panic(err) }
argv := append(os.Args, "-o", "child")
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)) }
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{}) }
var cmdFuse = &Command{ UsageLine: "fuse /mnt/mount/point -o \"filer=localhost:8888,filer.path=/\"", Short: "Allow use weed with linux's mount command", Long: `Allow use weed with linux's mount command
You can use -t weed on mount command: mv weed /sbin/mount.weed mount -t weed fuse /mnt -o "filer=localhost:8888,filer.path=/"
Or you can use -t fuse on mount command: mv weed /sbin/weed mount -t fuse.weed fuse /mnt -o "filer=localhost:8888,filer.path=/" mount -t fuse "weed#fuse" /mnt -o "filer=localhost:8888,filer.path=/"
To use without mess with your /sbin: mount -t fuse./home/user/bin/weed fuse /mnt -o "filer=localhost:8888,filer.path=/" mount -t fuse "/home/user/bin/weed#fuse" /mnt -o "filer=localhost:8888,filer.path=/"
To pass more than one parameter use quotes, example: mount -t weed fuse /mnt -o "filer='192.168.0.1:8888,192.168.0.2:8888',filer.path=/"
To check valid options look "weed mount --help" `, }
|