From 849f36c1ac2cbb26ceddd62244b57eea6e223aad Mon Sep 17 00:00:00 2001 From: danielflira Date: Sat, 29 May 2021 00:37:25 -0300 Subject: [PATCH] fix parameter multiple values --- weed/command/fuse.go | 277 ++++++++++++++++++++++++++----------------- 1 file changed, 167 insertions(+), 110 deletions(-) diff --git a/weed/command/fuse.go b/weed/command/fuse.go index 0a55e509c..74cf2bb70 100644 --- a/weed/command/fuse.go +++ b/weed/command/fuse.go @@ -12,124 +12,178 @@ func init() { cmdFuse.Run = runFuse // break init cycle } -func runFuse(cmd *Command, args []string) bool { - argsLen := len(args) - options := []string{} +type parameter struct { + name string + value string +} - // at least target mount path should be passed - if argsLen < 1 { - return false +func runFuse(cmd *Command, args []string) bool { + rawArgs := strings.Join(args, " ") + rawArgsLen := len(rawArgs) + option := strings.Builder{} + options := []parameter{} + + // 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]) + } + 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] != ','; 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]) + } + } - // first option is always target mount path - mountOptions.dir = &args[0] + options = append(options, parameter{name, option.String()}) + option.Reset() - // scan parameters looking for one or more -o options - // -o options receive parameters on format key=value[,key=value]... - for i := 0; i < argsLen; i++ { - if args[i] == "-o" && i+1 <= argsLen { - options = strings.Split(args[i+1], ",") - i++ + // 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]) } } - // for each option passed with -o - for _, option := range options { - // split just first = character - parts := strings.SplitN(option, "=", 2) - - // if doesn't key and value skip - if len(parts) != 2 { - continue - } + // get residual option data + if option.Len() > 0 { + // add value to pending option + options = append(options, parameter{option.String(), "true"}) + option.Reset() + } - key, value := parts[0], parts[1] - - // switch key keeping "weed mount" parameters - switch key { - case "filer": - mountOptions.filer = &value - case "filer.path": - mountOptions.filerMountRootPath = &value - case "dirAutoCreate": - if parsed, err := strconv.ParseBool(value); err != nil { - mountOptions.dirAutoCreate = &parsed - } else { - panic(fmt.Errorf("dirAutoCreate: %s", err)) - } - case "collection": - mountOptions.collection = &value - case "replication": - mountOptions.replication = &value - case "disk": - mountOptions.diskType = &value - case "ttl": - if parsed, err := strconv.ParseInt(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(value, 0, 32); err != nil { - intValue := int(parsed) - mountOptions.chunkSizeLimitMB = &intValue - } else { - panic(fmt.Errorf("chunkSizeLimitMB: %s", err)) - } - case "concurrentWriters": - if parsed, err := strconv.ParseInt(value, 0, 32); err != nil { - intValue := int(parsed) - mountOptions.concurrentWriters = &intValue - } else { - panic(fmt.Errorf("concurrentWriters: %s", err)) - } - case "cacheDir": - mountOptions.cacheDir = &value - case "cacheCapacityMB": - if parsed, err := strconv.ParseInt(value, 0, 64); err != nil { - mountOptions.cacheSizeMB = &parsed - } else { - panic(fmt.Errorf("cacheCapacityMB: %s", err)) - } - case "dataCenter": - mountOptions.dataCenter = &value - case "allowOthers": - if parsed, err := strconv.ParseBool(value); err != nil { - mountOptions.allowOthers = &parsed - } else { - panic(fmt.Errorf("allowOthers: %s", err)) - } - case "umask": - mountOptions.umaskString = &value - case "nonempty": - if parsed, err := strconv.ParseBool(value); err != nil { - mountOptions.nonempty = &parsed - } else { - panic(fmt.Errorf("nonempty: %s", err)) - } - case "volumeServerAccess": - mountOptions.volumeServerAccess = &value - case "map.uid": - mountOptions.uidMap = &value - case "map.gid": - mountOptions.gidMap = &value - case "readOnly": - if parsed, err := strconv.ParseBool(value); err != nil { - mountOptions.readOnly = &parsed - } else { - panic(fmt.Errorf("readOnly: %s", err)) - } - case "cpuprofile": - mountCpuProfile = &value - case "memprofile": - mountMemProfile = &value - case "readRetryTime": - if parsed, err := time.ParseDuration(value); err != nil { - mountReadRetryTime = &parsed - } else { - panic(fmt.Errorf("readRetryTime: %s", err)) - } + // scan each parameter + for i := 0; i < len(options); i++ { + parameter := options[i] + + switch parameter.name { + 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)) + } } } @@ -160,6 +214,9 @@ var cmdFuse = &Command{ 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" `, }