From d431c12a5f8abae2714357cf6468798f79a2b44a Mon Sep 17 00:00:00 2001 From: Dominic Della Valle Date: Sat, 12 Nov 2016 13:54:34 -0500 Subject: [PATCH] Windows root parse fix pt 2 License: MIT Signed-off-by: Dominic Della Valle --- commands/cli/parse.go | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/commands/cli/parse.go b/commands/cli/parse.go index c6faf374ce5c..077eada9cbdc 100644 --- a/commands/cli/parse.go +++ b/commands/cli/parse.go @@ -14,6 +14,7 @@ import ( files "github.com/ipfs/go-ipfs/commands/files" logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log" u "gx/ipfs/Qmb912gdngC1UWwTkhuW8knyRbcWeu5kqkxBpveLmW8bSr/go-ipfs-util" + ) var log = logging.Logger("commands/cli") @@ -399,8 +400,18 @@ func getArgDef(i int, argDefs []cmds.Argument) *cmds.Argument { const notRecursiveFmtStr = "'%s' is a directory, use the '-%s' flag to specify directories" const dirNotSupportedFmtStr = "Invalid path '%s', argument '%s' does not support directories" +const winDriveLetterFmtStr = "%q is a drive letter not a drive path, append a \\ to your input" func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (files.File, error) { + // resolve Windows relative dot paths like X:.\somepath + if len(fpath) >= 3 && fpath[0] != '/' && fpath[1:3] == ":." { + var err error + fpath, err = filepath.Abs(fpath) + if err != nil { + return nil, err + } + } + if fpath == "." { cwd, err := os.Getwd() if err != nil { @@ -429,10 +440,29 @@ func appendFile(fpath string, argDef *cmds.Argument, recursive, hidden bool) (fi } } - // special case for Windows drive roots i.e. X:\ - // drive path must be preserved and not converted to X: or / - if len(fpath) == 3 && fpath[0] != '/' && fpath[1:3] == `:\` { - return files.NewSerialFile(fpath, fpath, hidden, stat) + // special cases for Windows drive roots i.e. X:\ and their long form \\?\X:\ + // drive path must be preserved and not converted to `X:`, `X:.`, or `/` + switch len(fpath) { + case 3: + // X: will be cleaned to `X:.` which is not what is intended, a case for handling dot relative paths is above + if fpath[0] != '/' && fpath[1:3] == ":." { + return nil, fmt.Errorf(winDriveLetterFmtStr, fpath[:2]) + } + // X:\ needs to preserve the `\`, path.Base would remove it + if fpath[0] != '/' && fpath[1:3] == ":\\" { + return files.NewSerialFile(fpath, fpath, hidden, stat) + } + case 6: + // \\?\X: long prefix form of X: + if fpath[:4] == "\\\\?\\" && fpath[5] == ':' { + return nil, fmt.Errorf(winDriveLetterFmtStr, fpath) + } + case 7: + // \\?\X:\ long prefix form of X:\ + if fpath[:4] == "\\\\?\\" && fpath[5] == ':' && fpath[6] == '\\' { + fpath = string(fpath[4]) + ":\\" + return files.NewSerialFile(fpath, fpath, hidden, stat) + } } return files.NewSerialFile(path.Base(filepath.ToSlash(fpath)), fpath, hidden, stat)